Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose model testing require models

I have a problem testing my mongoose models

I have a structure like

  • app
    • models
      • Address
      • User
      • Organization
    • test

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?

like image 748
pfried Avatar asked Feb 01 '13 10:02

pfried


2 Answers

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.

like image 182
Leonid Beschastny Avatar answered Oct 12 '22 01:10

Leonid Beschastny


Best solution (IMO):

try {
  mongoose.model('config')
} catch (_) {
  mongoose.model('config', schema)
}
like image 38
merqlove Avatar answered Oct 12 '22 00:10

merqlove