【问题标题】:When using rewire and sinon fakeTimer, order matters?使用 rewire 和 sinon fakeTimer 时,顺序很重要吗?
【发布时间】:2016-01-19 19:08:05
【问题描述】:

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

首先,我使用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;

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

谁能详细解释一下?有没有办法可以在全局范围内使用需要注入的模块并重新连接,还是我总是必须在较低级别重新连接它们?

【问题讨论】:

  • 你知道你没有在每个测试用例之后重置时钟吗?为此,您需要使用afterEach 而不是after
  • @TJ。是的,确实如此,并且对于特定的测试用例是可以接受的

标签: javascript testing mocha.js setinterval sinon


【解决方案1】:

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

这些伪代码sn-ps演示了问题:

无需重新布线

// 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 的假计时器后重新接线来解决您的问题。

【讨论】:

  • 是否可以通过重新布线直接或间接重置全局变量(不太优雅的解决方案)?
猜你喜欢
  • 1970-01-01
  • 2012-12-11
  • 1970-01-01
  • 2014-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多