I'm using Mocha to test a method that has an asynchronous method inside of it. I'm stubbing that dependency with Sinon, and returning a resolved promise. But the promise is never resolved, or at least when the assertion is run it hasn't resolved yet.
Here is the method under test
function identify(traits) {
//THIS GETS CALLED SUCCESSFULLY
userService.get().then(function(user){
//CODE NEVER REACHES HERE
userService.set(user).then(function(){
//do something
}, function(){
//handle error
});
});
}
And here is the test
it('should identify a valid email address', function(){
var user = { email: '[email protected]' };
var getUserStub = sinon.stub(userService, "get");
var setUserStub = sinon.stub(userService, "set");
var userReturn = { email: '[email protected]', urls: ['http://some.url.com'] };
getUserStub.returns(Promise.resolve(userReturn));
//THE METHOD UNDER TEST
identifyController.identify(user);
sinon.assert.calledOnce(userService.get); //WORKS FINE
sinon.assert.calledOnce(userService.set); //FAILS
getUserStub.restore();
});
The assertion on userService.set fails, it says it was called 0 times. What am I doing wrong?
I've finally found the problem.
Promises are essentially asynchronous, but sinon calls are synchronous.
See this code pen.
What happens:
identifyController.identify(user);
get
, which returns a promise, which is asyncrhonous.sinon.assert.calledOnce
calls will happen in sequence, synchronouslyBy the time get
resolves itself and calls set
, because promises are non-blocking, the assertion will already have been executed, so it will fail.
So, you can do like this:
function identify(traits) {
return userService.get().then(function(user){
console.log('get');
userService.set(user).then(function(){
console.log('set');
//do something
});
});
}
And change this:
identify(user).then(function(){
sinon.assert.calledOnce(myObj.get); //WORKS FINE
sinon.assert.calledOnce(myObj.set); //WORKS FINE NOW
});