How do I test Ember.run.later with Sinon?

醉酒当歌 提交于 2019-12-06 03:48:16

问题


I have some Ember code that sets a timeout:

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

I'd like to test that using Sinon's fake clock. Here's what I tried:

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

But the expect always runs before the set. I also tried wrapping the clock.tick in a run-loop:

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

回答1:


Beware that sinon.useFakeTimers (by default on) overrides the window.Date. That becomes an issue once you already have a scheduled Ember runloop and the useFakeTimers() is turned on. This is because Backburner (the Ember.js runloop implementation) setTimeout /core scheduling method/ tries hard to optimize calling window.setTimeout (look for executeAt in ember.js)

After going through the sinon source I made the following mod to let those two get along nicely (gist). It instructs sinon not to touch the window.Date and also patches sinon.test() to wait few more ticks after the test body which allows scheduled timers to get executed and async codes

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



回答2:


The answer appears to be not putting the clock.tick in a run-loop, but the call that actually invokes Ember.run.later. Thus, the following does work:

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



回答3:


With ember 2.4.3 and sinon 0.5.0 seems to be fixed this kind of problems. sinon.useFakeTimers() works as expected with similar code on unit test:

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


来源:https://stackoverflow.com/questions/21896003/how-do-i-test-ember-run-later-with-sinon

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!