我正在尝试使用必须加载异步的配置为我的控制器创建mocha测试。以下是我的代码。但是,当运行mocha测试时,它不会运行任何测试,显示0 passing
。永远不会调用console.log
。我尝试在describe中执行before(next => config.build().then(next))
,但即使测试运行,也永远不会调用before
。有没有办法在运行任何测试之前加载一次配置?
'use strict';
const common = require('./common');
const config = require('../config');
config
.build()
.then(test);
function test() {
console.log(1);
describe('Unit Testing', () => {
console.log(2);
require('./auth');
});
}
答案 0 :(得分:3)
您应该使用--delay
选项运行Mocha,然后在构建完测试套件后使用run()
。以下是从您在问题中显示的代码派生的示例:
'use strict';
function test() {
console.log(1);
describe('Unit Testing', () => {
console.log(2);
it("test", () => {
console.log(3);
});
});
// You must use --delay for `run()` to be available to you.
run();
}
setTimeout(test, 1000);
我使用setTimeout
来模拟异步操作。使用--delay
和run()
可以构建一个异步计算结果的套件。但请注意,套件必须一次性构建。 (你不能在describe
内部有一个异步过程来调用it
。这不会起作用。)
你绝对不应该做的一件事是rob3c suggests:在一个钩子内调用describe
或it
(或两者)。这是一个偶尔人们所犯的错误,因此值得详细解决。问题是它不受Mocha支持,因此没有与从钩子内部调用describe
或it
相关联的已建立语义。哦,有可能编写简单的例子,这些例子可以按照人们的预期工作,但是:
当套件变得更加复杂时,套件的行为不再符合任何合理的行为。
由于没有与此方法相关的语义,较新的Mocha版本可能会以不同方式处理错误使用并破坏您的套件。
考虑这个简单的例子:
const assert = require("assert");
const p = Promise.resolve(["foo", "bar", "baz"]);
describe("top", () => {
let flag;
before(() => {
flag = true;
return p.then((names) => {
describe("embedded", () => {
for (const name of names) {
it(name, () => {
assert(flag);
});
}
});
});
});
after(() => {
flag = false;
});
it("regular test", () => {
assert(flag);
});
});
当我们运行它时,我们得到:
top
✓ regular test
embedded
1) foo
2) bar
3) baz
1 passing (32ms)
3 failing
// [stack traces omitted for brevity]
这里发生了什么?所有的测试都不应该通过吗?我们在flag
描述的true
挂钩中将before
设置为top
。我们在其中创建的所有测试都应将flag
视为true
,不是吗?线索在上面的输出中:当我们在钩子中创建测试时,Mocha会将测试放在某处,但它可能不在反映describe
块结构的位置代码。在这种情况下发生的事情是Mocha只是在top
描述之外的套件的最末端附加钩子中创建的测试,因此after
钩子运行之前动态创建的测试,我们得到一个反直觉的结果。
使用--delay
和run()
,我们可以编写一个行为方式与直觉相符的套件:
const assert = require("assert");
const p = Promise.resolve(["foo", "bar", "baz"]).then((names) => {
describe("top", () => {
let flag;
before(() => {
flag = true;
});
after(() => {
flag = false;
});
describe("embedded", () => {
for (const name of names) {
it(name, () => {
assert(flag);
});
}
});
it("regular test", () => {
assert(flag);
});
});
run();
});
输出:
top
✓ regular test
embedded
✓ foo
✓ bar
✓ baz
4 passing (19ms)
答案 1 :(得分:-1)
你可以完全分开测试和加载的逻辑,将加载器包装在一个阻止测试的promise中,直到执行配置(如果使用node8,则使用async / await非常简单,否则只是Promise.each结果)。
如果你真的不想这样做,你可以Promisify你的测试框架,这将允许你将所有describe / it块视为异步代码。
答案 2 :(得分:-1)
使用@Louis在其接受的答案中提到的--delay
命令行标记和run()
回调的问题是run()
是单个全局钩子那delays the root test suite。因此,你必须立即构建它们(如他所提到的),这可能使组织测试变得麻烦(至少可以说)。
但是,我希望尽可能避免使用魔术标记,而且我当然不希望在一个全局run()
回调中管理我的整个测试套件。幸运的是,有一种方法可以基于每个文件动态创建测试,并且它不需要任何特殊标志: - )
要使用异步获取的数据在任何测试源文件中动态创建It()
测试,您可以(ab)将before()
挂钩与占位符It()
一起使用测试以确保mocha等待运行before()
。以下是my answer to a related question的示例,为方便起见:
before(function () {
console.log('Let the abuse begin...');
return promiseFn().
then(function (testSuite) {
describe('here are some dynamic It() tests', function () {
testSuite.specs.forEach(function (spec) {
it(spec.description, function () {
var actualResult = runMyTest(spec);
assert.equal(actualResult, spec.expectedResult);
});
});
});
});
});
it('This is a required placeholder to allow before() to work', function () {
console.log('Mocha should not require this hack IMHO');
});