Bluebird promises freeze when using fake synon timer

The following test freezes when used with fake Sinon and Bluebird timers.

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

I am using Mocha (v2.2.5) with Bluebird (v2.9.33) and Sinon (v1.15.3).

I tried the suggestions offered in some discussions at Bluebird and Sinon, but I could not get the job done. This seems to be a problem with the way Sinon stubs setImmediate, but other than that I don't know how to solve it.

+8
bluebird sinon
source share
2 answers

You need to manually configure the fake timer as follows:

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

Btw, mocha has built-in promises support, so an even better way to do this is to fulfill return your promise:

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

In my experience, mixing promises and done callback style leads to all the problems and making it difficult to track errors. If using promises, try going back to it and look at a library like chai-as-promised . I promise this will make your tests more readable!

+6
source share

Recommendations:

Do not use fake timers, they can cause strange concurrency problems, as they synchronously call deferred functions - thus changing execution. Instead, use Mocha's built-in promises support, like:

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

But if you must

Please don’t, but you can say that bluebird starts its callbacks synchronously, I highly recommend against this and this will cause time problems in your application:

 Promise.setScheduler(function(fn){ return fn(); }); 
+2
source share

All Articles