摩卡异步执行顺序

Mocha async execution order

我正在使用 Mocha 对 AMD (requirejs) 模块进行 js 单元测试。由于模块需要通过requirejs加载,所以测试是异步的:

'use strict';

var chai = require('chai');
var should = chai.should();
var requirejs = require('requirejs');
requirejs.config({
    baseUrl: '../../',
    paths: {
        PieWidget: 'tools/scheduler/PieWidget'
    }
});

describe('PieWidget tests', function() {
    var PieWidget, pw1, pw2;
    before('Set up the PieWidget module', function(done) {
        requirejs(['PieWidget'], function(_) {
            PieWidget = _;
            done(); // tell Mocha we are now ready to run the tests
        });
    });

    // tests here
};

为了可读性和简洁性,我想说:

context('when the constructor is called', function() {
    pw1 = new PieWidget();
    it('should create a valid PieWidget', function() {
        pw1.should.exist;
        //todo check validity
    });
});

但是 Mocha 运行这些行时顺序不对。为了满足 Mocha,我必须:

context('when the constructor is called', function() {
    it('should create a valid PieWidget', function() {
        pw1 = new PieWidget();
        pw1.should.exist;
        //todo check validity
    });
});

在我看来,描述与逻辑不匹配,或者:

context('when the constructor is called', function() {
    before(function() {
        pw1 = new PieWidget();
    });
    it('should create a valid PieWidget', function() {
        pw1.should.exist;
        //todo check validity
    });
});

这看起来冗长且可读性差。有没有更好的方法来编写这段代码?

就 Mocha 而言,您发现的两种方法是有效的。

Mocha 分两个阶段工作:测试发现和测试执行。 (我不认为文档说明了这一点。)传递给 describecontext 的回调在测试发现期间被 Mocha 立即 调用。 beforebeforeEach 挂钩在测试执行期间被调用。 (请参阅此 answer 中输出数字的 console.log 调用的示例,以查看此顺序的实际操作。)在测试发现期间,您不能执行任何依赖于在测试执行期间执行的代码的内容。这是您的代码违反的原则:new PieWidget() 在 您的 before 钩子之前执行

现在,我认为这是编写测试的正确方法:

context('the constructor', function() {
    it('should create a valid PieWidget', function() {
        var pw1 = new PieWidget();
        pw1.should.exist;
        //todo check validity
    });
});

为什么?您最初的尝试没有成功,因为 Mocha 不允许,但假设它可以。并假设您的构造函数崩溃了。摩卡对这次失败有什么看法?我可以告诉你摩卡会做什么。它根本不会执行任何测试。如果您碰巧测试套件中的另一个对象,而该对象不受 PieWidget 有问题这一事实的影响,那么这些测试也不会 运行。摩卡会马上放弃。

如何将创作放入 before 挂钩中,您已经发现它有效。这仍然不是一个好主意。最终结果会有所不同,但它是一个坏主意的原因本质上是相同的:Mocha 不会 运行 尽可能多的测试。如果您的 PieWidget 有问题,那么钩子就会崩溃。 Mocha 将钩子中的崩溃解释为 测试套件本身 存在错误并将中止执行的标志。崩溃前执行的任何测试都可以,但不会执行崩溃后执行的任何测试。

按照我上面显示的方式进行操作可确保当您 运行 您的测试套件 Mocha 将 运行 进行最大数量的测试。 new PieWidget() 在您的测试中失败不会对任何其他测试产生任何影响。