Модели не загружаются должным образом при попытке тестирования 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 ...

  });