如何让 Mocha 加载定义全局钩子或实用程序的帮助程序.js文件

How can I make Mocha load a helper.js file that defines global hooks or utilities?

本文关键字:实用程序 帮助程序 文件 js Mocha 加载 全局 定义      更新时间:2023-09-26

我有一个名为test/helper.js的文件,用于在我的 Node.js 应用程序上运行 Mocha 测试。我的测试结构如下所示:

test/
test/helper.js    # global before/after
test/api/sometest.spec.js
test/models/somemodel.spec.js
... more here

必须加载文件helper.js,因为它包含我的测试套件的全局钩子。当我运行 Mocha 像这样执行整个测试套件时:

mocha --recursive test/

helper.js文件在我的测试之前加载,我的before钩子按预期执行。

但是,当我只运行一个特定测试时,测试前不会加载helper.js。这是我运行它的方式:

mocha test/api/sometest.spec.js

没有调用全局before,甚至没有console.log('I WAS HERE');.

那么如何让 Mocha 始终加载我的helper.js文件呢?

Mocha 没有任何名为 helper.js 的特殊文件的概念,它会在其他文件之前加载。

当您运行mocha --recursive时,您尝试执行的操作会起作用,因为 Mocha 恰好加载文件的顺序。由于helper.js比其他文件高一级,因此首先加载它。当您向 Mocha 指定单个文件时,Mocha 只会加载此文件,并且正如您发现的那样,您的helper.js文件根本不加载。

所以你要做的是加载一个文件,以便它将设置顶级("全局")钩子(例如 beforeafter等)。选项:

  1. 您可以以编程方式使用 Mocha,并按所需的顺序向其提供文件。

  2. 您可以强制自己在列出任何其他文件之前始终先在命令行上指定帮助程序文件。(我不会这样做,但这是可能的。

  3. 另一种选择是像我在此答案中详细介绍的那样组织您的套房。基本上,您有一个"顶级"文件,可以将套件的其余部分加载到其中。使用此方法,您将失去对单个文件运行 Mocha 的能力,但您可以使用--grep来选择正在运行的内容。

不能使用-r选项。它在运行套件之前加载一个模块,但不幸的是,加载的模块无法访问 Mocha 提供给您的测试的任何测试接口,因此它无法设置钩子。

我所做的是创建一个test/test_helper.js文件,该文件导出我创建的所有帮助程序:

// test/test_helper.js    
module.exports = {
    MyHelper: require('./helpers/MyHelper')
}

然后,我将帮助程序require我需要使用它的任何测试:

// test/spec/MySpec.js
var helper = require('../test_helper');
// Or if you need just "MyHelper"
var myHelper = require('../test_helper').MyHelper;
describe('MySpec', function () {
   // Tests here...
});

我更喜欢上述方法,因为它易于理解且灵活。你可以在我的演示中看到它的实际应用:https://github.com/paulredmond/karma-browserify-demo/tree/master/test<</p>

div class="answers">首先

,我肯定会使用mocha.opts,这样你就不必每次都包含你想要的选项。如前所述,一种选择是使用 --grep ,但我个人并不是它的忠实粉丝。它要求你以过于简单的方式命名所有内容。如果before钩子不是异步的,您可以在mocha.opts中使用--require。例如

#mocha.opts
--recursive
--require test/helpers.js

听起来这对你不起作用,因为你也需要全局after钩子。我所做的是每次都调用完整的测试套件,但是如果我正在开发并且只想测试一个套件,甚至一个特定的测试,我会使用排他性功能,only https://mochajs.org/#exclusive-tests。您可以将其设为it.only('...describe.only('... 如果这样做,它会遍历所有测试并完全按照完整测试工具进行设置,但随后仅执行指定的测试或套件。

现在你可以毫无问题地包含这些全局钩子。 @Louis提到您的helpers.js只是巧合地以正确的顺序加载。事实并非如此。如果将任何钩子放置在describe块之外,它会自动成为全局钩子。这可以通过将其放在自己的文件中来实现

// helpers.js
before(function() { console.log('testing...'); });

或在测试文件中

// some.spec.js
before(function() { console.log('testing...'); });
describe('Something', function() {
  it('will be tested', function() {
  ...
  });
});

显然,我认为将其放在自己的文件中更干净。(我称之为hooks.js)。关键是,这不是文件加载顺序的结果。

只有一个问题对其他人来说可能很明显,但我短暂地挣扎了一下——未放置在describe块中的钩子都是全局的。它们不是特定于目录的。因此,如果您将helpers.js复制到测试的子目录中,beforeafter 钩子现在将触发两次。此外,如果您在其中放置一个 beforeEach 钩子,它将在每次测试之前触发,而不仅仅是该目录中的那些测试。

无论如何,我知道这篇文章有点旧,但希望这会帮助其他有类似问题的其他人。

答案的后期补充:-

摩卡(截至撰写本文时为 v7.0.0)支持指定file选项:-
根据文档

  --file               Specify file(s) to be loaded prior to root suite
                       execution 
.

mocharc.json


{
    "watch-files": [
       "test/**/*.js"
    ],
    "recursive": true,
    "file": "test/setup"
}

./test/setup.js

const request = require('supertest');
const app = require('../app'); // express app
global.request = request(app);

值得一提的是:

我发现上面的设置无论如何都加载了所有.js文件,可能是因为 mocha 配置extension默认设置为 js。由于我有用.spec.js命名所有测试文件的约定,我可以通过添加"ignore": ["test/**/!(*.spec.js)"]

prepare(done => { console.log('do something asynchronously here') done() }, done => { console.log('asynchronously clean up after here') done() })

工作是一种享受。

在我们的项目中,我们使用的帮助程序有点像这样:

clientHelper = require("../../../utils/clientHelper")

您需要正确配置帮助程序的相对路径。

然后这样称呼它:

clientHelper.setCompanyId(clientId)