【问题标题】:How do I test Ember.run.later with Sinon?如何使用诗乃测试 Ember.run.later?
【发布时间】:2014-02-20 01:02:46
【问题描述】:

我有一些设置超时的 Ember 代码:

var MyObject = Ember.Object.extend({
  setFooToBarLater: function() {
    Ember.run.later(this, 'set', 'foo', 'bar', 500);
  }
});

我想用诗乃的假时钟来测试一下。这是我尝试过的:

var clock = sinon.useFakeTimers();
var myObject = MyObject.create();
myObject.setFooToBarLater();
clock.tick(600);
expect(myObject.get('foo')).to.be('bar');

但是expect 总是在set 之前运行。我还尝试将clock.tick 包装在一个运行循环中:

Ember.run(clock, 'tick', 600);

【问题讨论】:

  • 您是否尝试过增加 Sinon 刻度以查看它是否最终被设置? Ember.run.later 不保证回调何时执行。这取决于 Run 循环中的其他内容。
  • @pradeek 我将它提高了 10 倍,超出了我的预期。我想我可以继续前进!

标签: ember.js sinon


【解决方案1】:

注意 sinon.useFakeTimers(默认开启)会覆盖 window.Date。一旦你已经有一个预定的 Ember 运行循环并且 useFakeTimers() 被打开,这就会成为一个问题。这是因为 Backburner(Ember.js 的 runloop 实现)setTimeout /core 调度方法/努力优化调用 window.setTimeout(在 ember.js 中查找 executeAt

在查看了 sinon 源之后,我制作了以下 mod,让他们两个相处得很好(gist)。它指示 sinon 不要触摸 window.Date 并修补 sinon.test() 以在测试主体之后等待几个滴答声,从而允许执行计划的计时器和异步代码

sinon._originalUseFakeTimers = sinon.useFakeTimers;
sinon.useFakeTimers = function() {
    // make sure we don't override window.Date used in
    // Backburner.setTimeout() to optimize window.setTimeout() call numbers
    return sinon._originalUseFakeTimers.apply(this, [new Date().getTime(), "setTimeout", "setInterval", "clearTimeout", "clearInterval"]);
};

sinon._originalTest = sinon.test;
sinon.test = function(callback) {
    return sinon._originalTest.call(this, function() {
        callback.apply(this, arguments);

        // wait for further runloops to finish (2s is the mocha timeout)
        this.clock.tick(2000);
    });
};

【讨论】:

  • 太好了,这似乎可以再次运行 Ember,但我必须手动 tick 它,因为我使用 sinon-timers 1.9 作为独立版本。可悲的是,moment.js 不再接受虚假时间,而是返回真实时间。
  • 嘿@opichals,我尝试了您的解决方案但失败了。我提交了另一个问题,其中包含更多详细信息和演示。你能看看吗? stackoverflow.com/questions/28782076/…
【解决方案2】:

答案似乎不是将clock.tick 放入运行循环,而是实际调用Ember.run.later 的调用。因此,以下确实工作:

var clock = sinon.useFakeTimers();
var myObject = MyObject.create();
Ember.run(myObject, 'setFooToBarLater');
clock.tick(600);
expect(myObject.get('foo')).to.be('bar');

【讨论】:

【解决方案3】:

用 ember 2.4.3 和 sinon 0.5.0 似乎可以解决这类问题。 sinon.useFakeTimers() 在单元测试中使用类似代码按预期工作:

const clock = sinon.useFakeTimers();
assert.expect(1);
var MyObject = Ember.Object.extend({
    setFooToBarLater: function() {
      Ember.run.later(this, 'set', 'foo', 'bar', 500);
    }
  }), myObject = MyObject.create();
myObject.setFooToBarLater();
clock.tick(600);
assert.equal(myObject.get('foo'), 'bar');
clock.restore();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-30
    • 2015-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-04
    • 2019-07-07
    • 2017-05-12
    相关资源
    最近更新 更多