当使用Sinon的假定时器时,蓝鸟承诺冻结

与Sinon的假定时器和Bluebird一起使用时,以下testing会冻结。

var sinon = require('sinon'); var Promise = require('bluebird'); describe('failing test', function() { beforeEach(function() { this.clock = sinon.useFakeTimers(); }); afterEach(function() { this.clock.restore(); }); it('test', function(done) { Promise.delay(1000).then(function(){ done(); //This never gets called }); }); }); 

我正在用Bluebird(v2.9.33)和Sinon(v1.15.3)使用Mocha(v2.2.5)。

我尝试了Bluebird和Sinon在一些讨论中提出的build议,但是我无法做到这一点。 这似乎是一个问题与方式Sinon存根setImmediate但除此之外,我不知道如何解决这个问题。

您需要像这样手动步骤假计时器:

 describe('failing test', function() { it('test', function(done) { Promise.delay(1000).then(function(){ done(); //This never gets called }); // // ADVANCE THE CLOCK: // this.clock.tick(1000); }); }); 

顺便说一下,摩卡已经内置了对promise的支持,所以更好的方法是return你的诺言:

 describe('failing test', function() { it('test', function() { // No more "done" callback var p = Promise.delay(1000).then(function(){ console.log('done'); }); this.clock.tick(1000); return p; // Return the promise instead - mocha will take of the async magic goodness! }); }); 

根据我的经验,混合的承诺和donecallback风格导致各种麻烦和难以追踪错误。 在使用承诺时,尽量坚持回头看看图书馆,比如答应答 。 我向你保证它会使你的testing更加可读!

最佳做法:

不要使用假定时器,它们会导致奇怪的并发问题,因为它们同时调用延迟函数 – 从而改变执行。 而是使用摩卡的内置承诺支持:

 describe('failing test', function() { it('test', function(){ return Promise.delay(1000); // return the promise here, no `done` }); 

但是,如果你必须的

请不要,但你可以告诉蓝鸟同步运行它的callback,我强烈build议不要这样做,它导致你的应用程序的计时问题:

 Promise.setScheduler(function(fn){ return fn(); });