pfried
pfried

Reputation: 5089

Mongoose model testing require models

I have a problem testing my mongoose models

I have a structure like

Both models User and Organization need to know the model Address. My models are structured like:

module.exports = function (mongoose, config) {

    var organizationSchema = new mongoose.Schema({

        name : {
            type : String
        },
        addresses : {
            type : [mongoose.model('Address')]
        }

    });

    var Organization = mongoose.model('Organization', organizationSchema);

    return Organization;
};

In my normal app i require Address before requiring User and Organization and everything is fine. I now wrote tests for User and Organization. In order to have the Address model registered i call require('../models/Address.js') This works fine if i run one test. But if i run all tests in a batch i get an error because i tried to register Address twice.

OverwriteModelError: Cannot overwrite Address model once compiled.

How do i solve this problem?

Upvotes: 7

Views: 6411

Answers (5)

Robin ma
Robin ma

Reputation: 17

I use try/catch to tackle this problem and it works ok. But i think this not the best way of doing this.

try{
    var blog = mongoose.model('blog', Article);
} catch (error) {}

Upvotes: 0

merqlove
merqlove

Reputation: 3784

Best solution (IMO):

try {
  mongoose.model('config')
} catch (_) {
  mongoose.model('config', schema)
}

Upvotes: 3

regretoverflow
regretoverflow

Reputation: 2153

This question already has an answer, but for a unique way to accomplish this check out https://github.com/fbeshears/register_models. This sample project uses a register_models.js that includes all models from an array of file names. It works really well and you end up with all your models pretty much wherever you need them. Keep in mind node.js's cache will cache objects in your project while it's running.

Upvotes: 1

Anthony McCormick
Anthony McCormick

Reputation: 2744

I fixed this by patching r.js and making sure that all my modules used localRequire calls.

Checkout the thread here

https://github.com/jrburke/requirejs/issues/726

Upvotes: -1

Leonid Beschastny
Leonid Beschastny

Reputation: 51500

The problem is that you cant set mongoose model twice. The easiest way to solve your problem is to take advantage of node.js require function.

Node.js caches all calls to require to prevent your model from initializing twice. But you wrapping your models with functions. Unwrapping them will solve your problem:

var mongoose = require('mongoose');
var config = require('./config');

var organizationSchema = new mongoose.Schema({
    name : {
        type : String
    },
    addresses : {
        type : [mongoose.model('Address')]
    }
});

module.exports = mongoose.model('Organization', organizationSchema);

Alternative solution is to make sure that each model initialized only once. For example, you can initialize all you modules before running your tests:

Address = require('../models/Address.js');
User = require('../models/User.js');
Organization = require('../models/Organization.js');

// run your tests using Address, User and Organization

Or you can add try catch statement to your models to handle this special case:

module.exports = function (mongoose, config) {

    var organizationSchema = new mongoose.Schema({

        name : {
            type : String
        },
        addresses : {
            type : [mongoose.model('Address')]
        }

    });

    try {
        mongoose.model('Organization', organizationSchema);
    } catch (error) {}

    return mongoose.model('Organization');
};

Update: In our project we have /models/index.js file to handle everything. First, it calls mongoose.connect to establish connection. Then it requires every model in models directory and creates a dictionary of it. So, when we need some model (e.g. user) we requires it by calling require('/models').user.

Upvotes: 14

Related Questions