当使用重新连接和sinon fakeTimer时,订单有关系吗?

时间:2016-01-19 19:08:06

标签: javascript testing mocha setinterval sinon

在测试时间间隔的设置时,我遇到了这个问题。

首先,我使用sinon's fakeTimers来创建合适的定时环境。 rewire用作依赖注入库。

问题是,有时应用假计时器似乎在重新连接时失败,而在其他情况下,它完全正常工作。

请查看此设置:

test.js

'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);

    });

});

现在要包含第二个模块,其间隔为:

testmodule.js

'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;

现在,正如您所看到的,第二次测试失败了。这是在脚本之上使用模块的测试(也就是在全局范围内)。所以我怀疑这是因为重新连接是如何工作的以及假装时间安装的原因。

任何人都可以详细解释这个吗?有没有办法可以使用注入所需的模块重新连接全局范围,还是我总是需要在较低级别重新连接它们?

1 个答案:

答案 0 :(得分:2)

rewire会在var语句列表之前添加,以便将所有全局变量导入本地模块范围。因此,您可以在不影响其他模块的情况下更改全局变量。缺点是global属性的更改现在将被局部变量遮蔽。

这些伪代码片段证明了这个问题:

没有重新布线

// 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;
    ...
})()

您可以在设置sinon的假定时器后重新启动来解决您的问题。