CampbellSoftwareSolutions / mongoose-id-validator

Mongoose plug in to validate ObjectID references point to valid existing documents.
Other
47 stars 26 forks source link

MissingSchemaError in Mocha Tests #1

Closed c1moore closed 9 years ago

c1moore commented 9 years ago

I am trying to run some Mocha tests that all passed a few months ago, but they are all failing now. I have narrowed the problem down to mongoose-id-validator, which is throwing a MissingSchemaError for a schema I have confirmed is loaded.

Here is a simplified version of my test. The user schema references the _id field of event schema and when I attempt to save the user schema, the MissingSchemaError is thrown:

var should = require('should'),
    mongoose = require('mongoose');

console.log(mongoose.modelNames());
console.log(mongoose.model('Event').schema);

var Evnt = mongoose.model('Event'),
    User = mongoose.model('User'),
    Attendees = mongoose.model('Attendees');

var user, evnt;

describe("Model Unit Tests:", function() {
     before(function(done) {
          evnt = new Evnt({
               //Event definition
          });

          evnt.save(function() {
               user = new User({
                    //User definition
               });

               user.save(function() {
                    //MissingSchemaError thrown for model Event.
               });
          });
     });

The result of the console.log(mongoose.modelNames()) is:

[ 'Attendees', 'Candidate', 'Comment', 'Event', 'User' ]

The result of the console.log(mongoose.model('Event').schema) is:

{ paths: 
   { name: 
      { enumValues: [],
        regExp: null,
        path: 'name',
        instance: 'String',
        validators: [Object],
        setters: [Object],
        getters: [],
        options: [Object],
        _index: null },
     start_date: 
      { path: 'start_date',
        instance: 'Number',
        validators: [Object],
        setters: [],
        getters: [],
        options: [Object],
        _index: null },
     end_date: 
      { path: 'end_date',
        instance: 'Number',
        validators: [Object],
        setters: [],
        getters: [],
        options: [Object],
        _index: null },
     location: 
      { enumValues: [],
        regExp: null,
        path: 'location',
        instance: 'String',
        validators: [Object],
        setters: [Object],
        getters: [],
        options: [Object],
        _index: null },
     schedule: 
      { enumValues: [],
        regExp: null,
        path: 'schedule',
        instance: 'String',
        validators: [],
        setters: [Object],
        getters: [],
        options: [Object],
        _index: null,
        defaultValue: 'No schedule specified' },
     _id: 
      { path: '_id',
        instance: 'ObjectID',
        validators: [],
        setters: [Object],
        getters: [],
        options: [Object],
        _index: null,
        defaultValue: [Function: defaultId] },
     __v: 
      { path: '__v',
        instance: 'Number',
        validators: [],
        setters: [],
        getters: [],
        options: [Object],
        _index: null } },
  subpaths: {},
  virtuals: { id: { path: 'id', getters: [Object], setters: [], options: {} } },
  nested: {},
  inherits: {},
  callQueue: [ [ 'pre', [Object] ] ],
  _indexes: [ [ [Object], [Object] ] ],
  methods: {},
  statics: {},
  tree: 
   { name: { validate: [Object], trim: true, type: [Function: String] },
     start_date: { validate: [Object], type: [Function: Number] },
     end_date: { validate: [Object], type: [Function: Number] },
     location: { validate: [Object], trim: true, type: [Function: String] },
     schedule: 
      { default: 'No schedule specified',
        trim: true,
        type: [Function: String] },
     _id: { auto: true, type: [Function: ObjectId] },
     id: { path: 'id', getters: [Object], setters: [], options: {} },
     __v: [Function: Number] },
  _requiredpaths: undefined,
  discriminatorMapping: undefined,
  _indexedpaths: undefined,
  options: 
   { id: true,
     noVirtualId: false,
     _id: true,
     noId: false,
     read: null,
     shardKey: null,
     autoIndex: true,
     minimize: true,
     discriminatorKey: '__t',
     versionKey: '__v',
     capped: false,
     bufferCommands: true,
     strict: true,
     pluralization: true },
  _events: {} }

Obviously the schema is defined before the user model is saved. Here is the error message I receive:

  1) Model Unit Tests: "before all" hook:
     Uncaught MissingSchemaError: Schema hasn't been registered for model "Event".
Use mongoose.model(name, schema)
      at Mongoose.model (/home/c1moore/frankrs/node_modules/mongoose-id-validator/node_modules/mongoose/lib/index.js:323:13)
      at validateId (/home/c1moore/frankrs/node_modules/mongoose-id-validator/lib/id-validator.js:55:29)
      at EmbeddedDocument.<anonymous> (/home/c1moore/frankrs/node_modules/mongoose-id-validator/lib/id-validator.js:33:17)
      at /home/c1moore/frankrs/node_modules/mongoose/lib/schematype.js:623:19
      at Array.forEach (native)
      at ObjectId.SchemaType.doValidate (/home/c1moore/frankrs/node_modules/mongoose/lib/schematype.js:614:19)
      at /home/c1moore/frankrs/node_modules/mongoose/lib/document.js:974:9
      at process._tickDomainCallback (node.js:486:13)
martin-css commented 9 years ago

Thanks for reporting this issue.

Unfortunately I'm unable to reproduce this. I've updated to the latest version of mongoose (V3.8.25 at time of writing) and put in a simple integration test case which does not seem to be causing the issue.

Please feel free to amend the test case and submit a pull request if you can get this to re-occur. Without having access to all your test code it's difficult to diagnose what the issue would be. However, given it's the mongoose.model function that's failing I suspect it could be an issue with the test setup - e.g. are the models being defined on a different mongoose connection than is subsequently used in the test?

c1moore commented 9 years ago

Thank you for responding.

This test (and the entire project) is available on Github here: https://github.com/c1moore/cen3031project/blob/master/app/tests/attendees.server.model.test.js. However, the problem is occurring on all of my tests.

Other than running npm update no changes have been made to the code in the past 3 months and at that time all tests were passing as expected. As far as I can tell, only one connection is created and used throughout the code. I would suspect I would get an error trying to save the Event models I created if it were the case that multiple connections were created.

When run in development mode, connections to the database appear to work as expected, although I have not attempted to use an instance where mongoose-id-validator would be used yet.

martin-css commented 9 years ago

Had a quick look at your project. Your integration tests (they are not unit tests as they are interacting with the database) suffers issues which makes them non-deterministic. See this article on why this causes problems! Some of these problems are:

I don't think there's an issue with mongoose-id-validator, it looks like issues with your integration tests. Once you get your issues resolved, let me know if you still receive the original error and I'll have another look.

c1moore commented 9 years ago

Thank you for your suggestions. I will work on making these changes, but I do not believe these to be the main issue at the time. If you forked the project you must run npm update before running grunt test. After updating all npm packages, I receive the error above and no other test cases run (hence I do not see the same errors you are mentioning above).

I definitely agree that the changes you mentioned need to be made, but I still believe there may be a problem with mongoose-id-validator or something else that I am missing related to mongoose-id-validator. The MissingSchemaError appears to always be thrown on the Event schema, even when running other tests (i.e.: comment out/delete the Attendees integration tests file and run grunt test again and you will receive the same error for the Event schema). If you did fork the project, I would appreciate any suggestions you may have for getting past this error.

martin-css commented 9 years ago

Fixed in commit 19d77fab76585858e60219eef410cd8214e28b61.

I managed to reproduce the issue in your project after doing an npm update. The problem was due to the mongoose-id-validator referencing its own local copy of the mongoose package instead of the project's. Obviously your model did not exist in its own local copy.

The package definition has been updated and mongoose made a development dependency so the tests continue to run. However, you should find that removing this as an install dependency will fix your problems once you've ran npm update again.

Thanks for reporting. I'm not sure why this has arisen as an issue now and hasn't in the past. Presumably where models are stored by mongoose must have changed.

c1moore commented 9 years ago

Thank you for the suggestions and the fix. I am not sure what you mean by "removing this as an install dependency will fix your problems", but I have run npm update and my tests are running now