【问题标题】:Make Mocha wait for index.js to finish loading before running test files让 Mocha 在运行测试文件之前等待 index.js 完成加载
【发布时间】:2019-11-03 08:34:47
【问题描述】:

我的文件夹结构为:

- 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"

这就是奇怪的地方让我变得更好。基本上它在 anything 之前加载 passwords.controller.js,这是因为 --recursive 选项。这不应该发生,因为 index.js 需要先加载,以便它可以在任何测试运行之前连接到猫鼬等,如果没有,那么来自 passwords.controller.js 的这个 sn-p 将抛出 MissingSchemaError: Schema hasn't been registered for model "Password".,因为模型 @987654333 @此时尚未设置:

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

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

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

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

【问题讨论】:

  • 你有最小的 repo 可以测试吗?将节省时间来提供解决方案
  • 为什么你的测试需要索引? - 您想将索引拆分为 2 个文件:app.js 和 server.js - 您不应该在 mocha 测试中监听,而应该在生产代码中监听。 - 如果你想在测试中连接到猫鼬 - 使用 before()
  • @BrentGreeff 我的设置基于此github.com/kunalkapadia/express-mongoose-es6-rest-api,它需要每个测试文件中的index.js 文件,而这又需要express.js 文件。由于我正在使用多个 mongoose 实例,因此我必须调整代码以便它异步加载应用程序,这就是它必须首先加载 index.js 文件的时候,而不是在测试文件需要它的时候。我不确定你说测试不应该听是什么意思,当然他们必须听,否则测试将无法使用数据库。
  • @TarunLalwani 它基于这个github.com/kunalkapadia/express-mongoose-es6-rest-api,我只是重写了index.js 文件,基本上是为了异步加载应用程序。也许这对你有帮助?
  • @Chrillewoodz - 你的网络服务器正在监听。它不应该在摩卡测试中。我不知道为什么你需要像这样构造你的文件。我也不明白为什么你不能从你的测试中明确地连接到数据库。

标签: node.js asynchronous async-await mocha.js


【解决方案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 仅加载测试。另一个好处是在生产中你可以跳过这个文件夹

【讨论】:

    【解决方案2】:

    您可以在技术上运行您的 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
    });
    

    【讨论】:

    • 如果测试位于不同的文件夹中怎么办?是否有运行--recursive 的编程方式?
    • 您可以使用 mocha.addFile 在单独的文件夹中运行测试,但运行递归标志,它只是一个 cli 函数
    猜你喜欢
    • 2014-10-21
    • 2021-01-23
    • 1970-01-01
    • 2016-08-07
    • 2017-06-15
    • 1970-01-01
    • 2020-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多