Last active
August 29, 2015 14:05
-
-
Save virtualandy/8e3665068469524357f7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
var chai = require("chai"); | |
var sinon = require("sinon"); | |
var sinonChai = require("sinon-chai"); | |
chai.should(); | |
chai.use(sinonChai); | |
function asyncHello(name, delay, cb) { | |
setTimeout(function() { | |
console.log("running after ", delay); | |
cb("hello " + name); | |
}, delay); | |
} | |
suite('Mega Suite', function(){ | |
suite("testing async hello", function() { | |
test('should call the callback', function(done) { | |
var cb = sinon.spy(); | |
asyncHello("foo", 500, cb); | |
cb.should.have.been.called(); | |
done(); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ cat package.json | |
{ | |
"name": "mocha-meetup", | |
"version": "0.0.0", | |
"description": "", | |
"main": "index.js", | |
"author": "", | |
"license": "ISC", | |
"devDependencies": { | |
"chai": "^1.9.1", | |
"mocha": "^1.21.4", | |
"sinon": "^1.10.3", | |
"sinon-chai": "^2.5.0" | |
}, | |
"scripts": { | |
"test": "node_modules/.bin/mocha --ui=tdd test/*.js" | |
} | |
} | |
@focusaurus sorry just seeing this. Thanks for the tip.
What's the 'right' way to use Sinon to spy on a potentially async function like that? Really just thinking of this in a functional/integration type test, where I want to verify that the right module does the right thing based on given input.
In this case I wanted to stub/spy on the function that makes the call so that it doesn't hit the wire, more as an example than anything real.
Ken Powers has a great writeup on some of Sinon's advance features. I guess one approach is to use fake timers and skip using Mocha's done()
functionality.
Based on that blog, I tweaked the test to look like:
suite('Mega Suite', function(){
suite("testing async hello", function() {
beforeEach(function () {
// Overwrite the global timer functions (setTimeout, setInterval) with Sinon fakes
this.clock = sinon.useFakeTimers();
});
afterEach(function () {
// Restore the global timer functions to their native implementations
this.clock.restore();
});
test('should call the callback', function() {
var spy = sinon.spy();
function asyncHello(name, delay, cb) {
setTimeout(function() {
console.log("running after ", delay);
cb("hello " + name);
}, delay);
}
asyncHello("foo", 1000, spy);
this.clock.tick(999);
spy.should.have.not.been.called;
this.clock.tick(1);
// Now the spy should have been called
spy.should.have.been.called;
spy.should.have.been.calledOnce;
});
});
});
Which works. Using done seems cleaner/simpler, though.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The problem is lines 20-22 all execute in the same tick (calling asyncHello and asserting the callback was called), but the asyncHello callback doesn't actually get invoked until a later tick. You can change the entire test function body to just this call
asyncHello("foo", done);
and it will pass.