I'm trying to use mocha to test my express app. My folder structure is:
myapp
|-app
|--models
|-test
|--mocha-blanket.js
|--mocha
|--karma
|-server.js
server.js
is my express server. I had that before in options.require
, but the documentation said to use a blanket.js
. My mocha-blanket.js
is:
var path = require('path');
var srcDir = path.join(__dirname, '..', 'app');
require('blanket')({
// Only files that match the pattern will be instrumented
pattern: srcDir
});
My Gruntfile has:
mochaTest:
options:
reporter: "spec"
require: 'test/mocha-blanket.js'
# require: "server.js"
coverage:
options:
reporter: 'html-cov',
captureFile: 'mocha-coverage.html'
src: ["test/mocha/**/*.js"]
The error I'm getting is:
>> Mocha exploded!
>> MissingSchemaError: Schema hasn't been registered for model "Company".
>> Use mongoose.model(name, schema)
>> at Mongoose.model (/myapp/node_modules/mongoose/lib/index.js:315:13)
>> at Object.<anonymous> (/myapp/test/mocha/controllers/company.js:4:22)
>> at Module._compile (module.js:456:26)
>> at Module._extensions..js (module.js:474:10)
I'm sure I'm doing something (or a lot of things) incorrectly. But I'm not sure what. Any ideas?
I think your testing code isn't properly initializing your application, specifically initialization of the Mongoose schema and models.
In mocha/controllers/company.js
, you're probably using code similar to this:
var Company = mongoose.model('Company');
However, that will raise the error that you're getting if the initialization of the Company
model (where you hook up the model with the schema) was skipped.
To give a very short standalone example, this code will fail with the same error:
var mongoose = require('mongoose');
var Company = mongoose.model('Company');
This code, with the added initialization, works fine:
var mongoose = require('mongoose');
mongoose.model('Company', new mongoose.Schema());
var Company = mongoose.model('Company');
You get this error because you have not explicitly 'loaded' your models to mongoose. I have solved this issue with: 1 Models init script:
module.exports = {
storage:{
sample: require('models/storage/sample'),
other models scoped to "storage" connection...
},
accounts: {
company: require('models/accounts/company'),
etc...
}
};
this is kicked off once on each mongoose.createConnection callback:
var accounts = mongoose.createConnection(config.get('mongoose:accounts:uri'), config.get('mongoose:accounts:options'), function(err){
if (err) throw err;
console.log('connection to accounts database open');
require('models/init').accounts;
});
it runs all your models declaration code and later in tests you have all your models registered.
Ensure database connection middleware. This guy makes you sure that connections are open and init scripts run successfully.
var storage = require('models').storage;
var accounts = require('models').accounts;
module.exports = function ensureDbConnectionMiddleware(req, res, next){
var count = 0;
var interval = setInterval(function(){
if (storage._readyState === 1 && accounts._readyState === 1){
clearInterval(interval);
return process.nextTick(function(){
next();
});
}else{
if (count++ > 50){
res.json({status: 0, message: 'Database offline'});
throw new Error('Database is offline');
}
}
}, 100);
};
Later in tests
var should = require('should');
var express = require('express');
var app = express();
app.use(express.bodyParser());
app.use(require('middleware/ensureDbConnection'));
require('routes')(app);
//etc...
I'm not sure if this is the best solution, but it works quite well. It certainly has one major caveat: you have to keep all this stuff in sync. However, you can try to delegate this to grunt.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With