vendredi 26 février 2016

Problems loading Mongoose models in separate unit test files - Using Mockgoose for Mongoose test

Whenever a Mongoose model is attempted to load after it's already loaded, an error is thrown, such as:

error: uncaughtException: Cannot overwrite Account model once compiled. date=Fri Feb 26 2016 10:13:40 GMT-0700 (MST), pid=19231, uid=502, gid=20, cwd=/Users/me/PhpstormProjects/project, execPath=/usr/local/Cellar/node/0.12.4/bin/node, version=v5.2.0, argv=[/usr/local/Cellar/node/0.12.4/bin/node, /usr/local/Cellar/node/0.12.4/bin/lab], rss=73306112, heapTotal=62168096, heapUsed=29534752, loadavg=[1.6005859375, 1.84716796875, 1.8701171875], uptime=648559 OverwriteModelError: Cannot overwrite Account model once compiled.

Which I'm fine with, but now that I'm writing unit tests for my models, I'm running into an issue.

Just some basic info about the file structure...

I have all the Mongoose models in separate files, located inside the src/models/ folder, and to load these models, one simply has to require the folder, passing a Mongoose object to it, and the src/models/index.js file will load all the models, and return an object of the models. The index.js file can be seen here (And not that its relevant, but the model names are basically the filename, without the .js)

Now the Unit tests for the models are also split up into separate files. Theres one test file for each model. And even though each unit test file focuses on a specific model, some of them use other models as well (for before/after tasks).

Initial Problem

I just created the 2nd unit test file, and when I execute each one independently, they work just fine. But when I execute all of them, I receive the above error, stating that I'm attempting to load the models more than once. Which since I require the ./models in each unit test case, I am loading them more than once.

First Resolution Attempt

I thought that maybe I could clear all of the loaded models via after() in each separate unit test file, like so:

after(function(done) {
    mongoose.connection.close(function() {
        mongoose.connection.models = {}
        done()
    })
})

Which didn't work at all (No new errors, but the same Cannot overwrite Account model once compiled error(s) persisted)

Second Resolution Attempt (semi-successful)

Instead of the models throwing an error on the last line, when it attempts to return the Mongoose.model(), I insert some logic in the top of the model, to check if the model is loaded, and if so, return that model object:

const thisFile  = path.basename( __filename ).match( /(.*)\.js$/ )[ 1 ]
const modelName = _.chain( thisFile ).toLower().upperFirst().value()

module.exports = Mongoose => {
    // Return this model, if it already exists
    if( ! _.isUndefined( Mongoose.models[ modelName ] ) )
        return Mongoose.models[ modelName ]

    const Schema = Mongoose.Schema

    const appSchema = new Schema( /* ..schema.. */)

    return Mongoose.model( modelName, appSchema )
}

I'm trying that out in my models right now, and it seems to work alright, (alright meaning I don't get the errors listed above, saying I'm loading models multiple times)

New Problem

Now whenever the unit tests execute, I receive an error, the error displays once per a model, but its the same error:

$ lab

  ..................................................
  ...

Test script errors:

Cannot set property '0' of undefined
      at emitOne (events.js:83:20)
      at EventEmitter.emit (events.js:170:7)
      at EventEmitter.g (events.js:261:16)
      at emitNone (events.js:68:13)
      at EventEmitter.emit (events.js:167:7)

Cannot set property '0' of undefined
      at emitOne (events.js:83:20)
      at EventEmitter.emit (events.js:170:7)
      at EventEmitter.g (events.js:261:16)
      at emitNone (events.js:68:13)
      at EventEmitter.emit (events.js:167:7)

Cannot set property '0' of undefined
      at emitOne (events.js:83:20)
      at EventEmitter.emit (events.js:170:7)
      at EventEmitter.g (events.js:261:16)
      at emitNone (events.js:68:13)
      at EventEmitter.emit (events.js:167:7)

There were 3 test script error(s).

53 tests complete
Test duration: 1028 ms
No global variable leaks detected

There isn't too much details to go off of in that stack trace..

I'm not sure if its caused by the code I added into each model, checking if it's already loaded, if it was, it would either show up when I execute a single unit test, or it would only show that Cannot set property '0' of undefined twice (Once for a successful initial model load, then twice for the next two... I would think)

If anyone has any input, I would very much appreciate it! Thanks

Aucun commentaire:

Enregistrer un commentaire