Javascript 使用rewire和sinon fakeTimer时,订单很重要吗?

Javascript 使用rewire和sinon fakeTimer时,订单很重要吗?,javascript,testing,mocha.js,setinterval,sinon,Javascript,Testing,Mocha.js,Setinterval,Sinon,在使用定时间隔测试设置时,我遇到了这个问题 首先,我使用创建正确的时间环境。用作依赖项注入库 问题是,有时当涉及重新布线时,应用假定时器似乎失败了,而在其他一些情况下,它工作正常 请检查此设置: test.js 现在包括第二个具有间隔的模块: testmodule.js 现在,正如您所看到的,第二个测试失败了。这是使用模块的测试,因为它是脚本顶部所需的(在全局范围内也称为)。所以我怀疑这是因为重新布线的工作方式以及Faketimer安装的时间 有人能详细解释一下吗?有没有一种方法可以在全局范围内

在使用定时间隔测试设置时,我遇到了这个问题

首先,我使用创建正确的时间环境。用作依赖项注入库

问题是,有时当涉及重新布线时,应用假定时器似乎失败了,而在其他一些情况下,它工作正常

请检查此设置:

test.js

现在包括第二个具有间隔的模块:

testmodule.js

现在,正如您所看到的,第二个测试失败了。这是使用模块的测试,因为它是脚本顶部所需的(在全局范围内也称为)。所以我怀疑这是因为重新布线的工作方式以及Faketimer安装的时间


有人能详细解释一下吗?有没有一种方法可以在全局范围内使用注入所需模块并重新布线,还是必须始终在较低级别上重新布线?

重新布线预先列出
var
语句,以便将所有全局模块导入到本地模块范围内。因此,您可以在不影响其他模块的情况下更改全局变量。缺点是,对
global
属性的更改现在将被局部变量隐藏

这些伪代码片段演示了问题:

无需重新布线 重新布线
设置sinon的假计时器后,您可以通过重新布线来解决问题。

您是否意识到在每个测试用例后都没有重置时钟?要做到这一点,您需要在每次之后使用
,而不是在
之后使用
@TJ。是的,这是正确的,并且对于特定的测试用例是可以接受的。是否可以通过重新布线(一种不太优雅的解决方案)直接在系统中重置全局变量?
'use strict';

require('should');
var sinon = require('sinon');
var rewire = require('rewire');

// this sample will not fall under the fake timer
var SampleGlobal = rewire('./testmodule');

describe('Sinon fake timer with rewirejs', function() {

    var clock;

    before(function() {
        clock = sinon.useFakeTimers();
    });

    after(function() {
        clock.restore();
    });

    it('work for locally rewired module', function() {

        var spy = sinon.spy();

        // locally inject-required module
        var Sample = rewire('./testmodule');

        new Sample().on('test', spy);

        spy.callCount.should.equal(0);

        clock.tick(5000);

        spy.callCount.should.equal(1);

    });

    it('break when rewired from global scope', function() {

        var spy = sinon.spy();

        // the module is globally inject-required
        new SampleGlobal().on('test', spy);

        spy.callCount.should.equal(0);

        clock.tick(5000);

        spy.callCount.should.equal(1);

    });

});
'use strict';

var EventEmitter = require('events').EventEmitter;
var util = require('util');

function Sample() {

    this.h = setInterval(this.emit.bind(this, 'test'), 5000);

}

util.inherits(Sample, EventEmitter);

module.exports = Sample;
// Global scope
var setTimeout = global.setTimeout;

(function () {
    // Module scope. Node.js uses eval() and an IIFE to scope variables.
    ...
})()
// Global scope
var setTimeout = global.setTimeout;

(function () {
    // Module scope.
    var setTimeout = global.setTimeout;
    ...
})()