让Mocha等待index.js完成加载,然后再运行测试文件

时间:2019-06-20 13:45:20

标签: node.js asynchronous async-await mocha

我的文件夹结构为:

- app
  - config
    - config.js // environment variables
    - express.js // creates an express server
  - passwords
    - passwords.controller.js
    - passwords.route.js
    - passwords.test.js
  - index.js // main app file

我的索引文件异步加载应用程序:

function initMongoose() {

  ...

  return mongoose.connect(config.mongo.host, {useNewUrlParser: true, keepAlive: 1})
    .then((connection) => {

      // Password is a function which connects the Password schema to the given connection
      Password(connection);
    })
    .catch((e) => {
      throw new Error(`Unable to connect to database: ${config.mongo.host}`);
    });
}

async init() {

  await initMongoose();

  const app = require('./config/express');
  const routes = require('./index.route');

  app.use('/api', routes);

  ...

  app.listen(3000, () => {
    console.log('server started');
  });
}

module.exports = init();

我的测试文件的结构如下:

// Load the app async first then continue with the tests
require('../index').then((app) => {

  after((done) => {
    mongoose.models = {};
    mongoose.modelSchemas = {};
    mongoose.connection.close();
    done();
  });

  describe('## Passwords API', () => {
    ...
  });
});

我正在像这样开始测试:

"test": "cross-env NODE_ENV=test ./node_modules/.bin/mocha --ui bdd --reporter spec --colors server --recursive --full-trace"

在这里,怪异使我变得更好。基本上,它先加载passwords.controller.js,然后再加载其他任何东西,这是因为使用了--recursive选项。由于index.js需要首先加载,因此它可以在运行任何测试之前连接到猫鼬等,因此不会发生这种情况,否则,passwords.controller.js中的此代码段将抛出MissingSchemaError: Schema hasn't been registered for model "Password".,因为此时尚未设置模型Password

const Password = mongoose.connection.model('Password');

因此,我尝试在--require ./index.js选项之前添加--recursive,这确实在passwords.controller.js之前加载了其他文件,但是后者仍在index.js完成之前运行。

解决方案here不起作用,因为index.js没有先运行。

如何在运行任何测试文件之前修改test脚本以使index.js完成?

2 个答案:

答案 0 :(得分:1)

describe('## Passwords API', function() {
  let appInstance;

   before((done) => {
      require('index.js').then((app) => {
          appInstance = app
          done();
      });
   });
});

参考:https://mochajs.org/#asynchronous-hooks

另一种可能的模式是拥有一个特殊的帮助文件。那就像单例或某种缓存。这允许服务器仅引导一次,并为所有测试共享。请注意,这可能会在单元测试中引起不良的副作用,但可以加快不影响应用程序对象的测试速度。

例如testUtil.js

let app = null;
async function getApp(){
   if(app){
      return app;
   }
   app = await require('index.js')
   return app
}

module.export = {
   getApp,
}

并在您的测试文件中

const helper = require('[your path]/testUtil.js')
describe('## Passwords API', function() {
  let appInstance;

   before((done) => {
      helper.getApp().then((app) => {
          appInstance = app
          done();
      });
   });
});

我还建议将所有测试放在单独的文件夹中(也许称为“测试”)。这样可以确保--recursive仅加载测试。另一个好处是,在生产中,您可以跳过此文件夹

答案 1 :(得分:0)

从技术上讲,您可以运行index.js文件,而不是通过npm test(CLI)使用mocha,实际上可以在index.js之后以编程方式通过mocha运行测试。 Mocha Programmatically example

import Mocha from 'mocha'; 
import fs from 'fs';
import path from 'path';

// Instantiate a Mocha instance.
const mocha = new Mocha();

const testDir = 'some/dir/test'

// Add each .js file to the mocha instance
fs.readdirSync(testDir).filter(function(file) {
    // Only keep the .js files
    return file.substr(-3) === '.js';

}).forEach(function(file) {
    mocha.addFile(
        path.join(testDir, file)
    );
});

// Run the tests.
mocha.run(function(failures) {
  process.exitCode = failures ? 1 : 0;  // exit with non-zero status if there were failures
});