如何让 Mocha 加载定义全局挂钩或实用程序的 helper.js 文件?
How can I make Mocha load a helper.js file that defines global hooks or utilities?
我有一个名为 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
文件根本没有加载。
所以你想要做的是加载一个文件,这样它将设置顶级 ("global") 挂钩(例如 before
、after
等)。选项:
您可以使用 Mocha programmatically 并按照您想要的顺序向其提供文件。
您可以强迫自己始终在命令行 first 上指定您的帮助程序文件,然后再列出任何其他文件。 (我不会这样做,但这是可能的。)
另一种选择是按照我在 this answer 中详述的方式组织您的套件。基本上,您有一个 "top level" 文件,可以将套件的其余部分加载到其中。使用这种方法,您将失去 运行ning Mocha 对单个文件的能力,但您可以使用 --grep
到 select 正在 运行.
您不能使用-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
首先,我肯定会使用 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
复制到测试的子目录中,before
和 after
挂钩现在将触发两次。此外,如果您在其中放置一个 beforeEach
挂钩,它将在每次测试之前触发,而不仅仅是该目录中的那些测试。
无论如何,我知道这个 post 有点旧,但希望这能帮助其他有类似问题的人。
在尝试了各种方法让我的测试连接到数据库之后,我才想到这个问题,然后 运行 在我的 models
上进行了一堆 crud
测试。
然后我发现 mocha-prepare 解决了我的问题。
在您的 helper.js
文件中,您可以只定义一个 prepare
函数。
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)
迟到的答案补充:-
Mocha(撰写本文时为 v7.0.0)支持指定 file
作为选项:-
根据 docs
--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)"]
来忽略其他文件
我有一个名为 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
文件根本没有加载。
所以你想要做的是加载一个文件,这样它将设置顶级 ("global") 挂钩(例如 before
、after
等)。选项:
您可以使用 Mocha programmatically 并按照您想要的顺序向其提供文件。
您可以强迫自己始终在命令行 first 上指定您的帮助程序文件,然后再列出任何其他文件。 (我不会这样做,但这是可能的。)
另一种选择是按照我在 this answer 中详述的方式组织您的套件。基本上,您有一个 "top level" 文件,可以将套件的其余部分加载到其中。使用这种方法,您将失去 运行ning Mocha 对单个文件的能力,但您可以使用
--grep
到 select 正在 运行.
您不能使用-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
首先,我肯定会使用 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
复制到测试的子目录中,before
和 after
挂钩现在将触发两次。此外,如果您在其中放置一个 beforeEach
挂钩,它将在每次测试之前触发,而不仅仅是该目录中的那些测试。
无论如何,我知道这个 post 有点旧,但希望这能帮助其他有类似问题的人。
在尝试了各种方法让我的测试连接到数据库之后,我才想到这个问题,然后 运行 在我的 models
上进行了一堆 crud
测试。
然后我发现 mocha-prepare 解决了我的问题。
在您的 helper.js
文件中,您可以只定义一个 prepare
函数。
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)
迟到的答案补充:-
Mocha(撰写本文时为 v7.0.0)支持指定 file
作为选项:-
根据 docs
--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)"]