Модели не загружаются должным образом при попытке тестирования Mocha
Я пытаюсь использовать mocha для тестирования своего экспресс-приложения. Моя структура папок:
myapp
|-app
|--models
|-test
|--mocha-blanket.js
|--mocha
|--karma
|-server.js
server.js
- мой экспресс-сервер. У меня было это раньше в options.require
, но документация сказала использовать blanket.js
. Мой mocha-blanket.js
:
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 имеет:
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"]
Ошибка, которую я получаю:
>> 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)
Я уверен, что я что-то делаю (или много чего) неправильно. Но я не уверен, что. Любые идеи?
Ответы
Ответ 1
Я думаю, что ваш тестовый код неправильно инициализирует ваше приложение, в частности, инициализацию схемы и моделей Mongoose.
В mocha/controllers/company.js
вы, вероятно, используете код, похожий на этот:
var Company = mongoose.model('Company');
Тем не менее, это приведет к возникновению ошибки, которую вы получите, если была проигнорирована инициализация модели Company
(где вы подключили модель со схемой).
Чтобы дать очень короткий отдельный пример, этот код завершится с той же ошибкой:
var mongoose = require('mongoose');
var Company = mongoose.model('Company');
Этот код с добавленной инициализацией отлично работает:
var mongoose = require('mongoose');
mongoose.model('Company', new mongoose.Schema());
var Company = mongoose.model('Company');
Ответ 2
Вы получаете эту ошибку, потому что вы явно не загрузили свои модели в мангуст. Я решил эту проблему:
1 Модели init script:
module.exports = {
storage:{
sample: require('models/storage/sample'),
other models scoped to "storage" connection...
},
accounts: {
company: require('models/accounts/company'),
etc...
}
};
это срабатывает один раз на каждом обратном вызове mongoose.createConnection:
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;
});
он запускает весь код объявления моделей, а затем в тестах вы регистрируете все свои модели.
Обеспечьте промежуточное ПО для подключения к базе данных. Этот парень убеждает вас в том, что соединения открыты, а скрипты init успешно выполняются.
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);
};
Позже в тестах
var should = require('should');
var express = require('express');
var app = express();
app.use(express.bodyParser());
app.use(require('middleware/ensureDbConnection'));
require('routes')(app);
//etc...
Я не уверен, что это лучшее решение, но оно работает очень хорошо.
У него, безусловно, есть одно важное предостережение: вы должны синхронизировать все это. Однако вы можете попытаться делегировать это, чтобы хрюкать.
Ответ 3
Для Mocha вам нужно дождаться открытия соединения MongoDB, прежде чем пытаться использовать модель.
var mongoose = require('mongoose');
var Company;
describe('Unit Test', function () {
before(function(done) {
mongoose.connection.once('open', function() {
Company = mongoose.model('Company');
done();
});
});
... tests here ...
});