Getting better feedback from sinon stubs
Sinon is an extremely powerful tools for writting unit tests. It helps to create standalone spies, stubs and mocks to isolate functionallity.
Setting up Sinon
The documentation suggests you can, for example, create a spy like so:
it('calls the original function', function () { var callback = sinon.spy(); var proxy = once(callback); proxy(); assert(callback.called); });
Which passes just fine:
$ ./node_modules/.bin/mocha ✓ calls the original function 1 passing (7ms)
However, it doesn't give excellent feedback on failure.
$ ./node_modules/.bin/mocha 1) calls the original function 0 passing (8ms) 1 failing 1) calls the original function: AssertionError [ERR_ASSERTION]: false == true + expected - actual -false +true at Context.<anonymous> (test/test-spec.js:21:5)
Getting Better Feedback
Luckily, sinon ships with a built in way of writting assertions that provide excellent feedback
sinon.assert.called(callback);
Which on failure provides the very readable:
$ ./node_modules/.bin/mocha 1) calls the original function 0 passing (9ms) 1 failing 1) calls the original function: AssertError: expected spy to have been called at least once but was never called at Object.fail (node_modules/sinon/lib/sinon/assert.js:96:21) at failAssertion (node_modules/sinon/lib/sinon/assert.js:55:16) at Object.assert.(anonymous function) [as called] (node_modules/sinon/lib/sinon/assert.js:80:13) at Context.<anonymous> (test/test-spec.js:23:18)
Multple Spies
In some cases your spec might require more than one anonymous spy. Like in the following somewhat contrived example:
it('returns a user', function () { var req = { locals: {user: "a user"} }; var res = { json: sinon.spy() }; var next = sinon.spy(); controller(req, res, next); sinon.assert.called(res.json); sinon.assert.called(next); });
Which on failure gives the generic message:
AssertError: expected spy to have been called at least once but was never called
You can trick sinon into naming the spy or stub by passing a named function to the spy. For example:
var next = sinon.spy(function next() {});
Which gives the more useful feedback:
AssertError: expected next to have been called at least once but was never called
What's next
Sinon has lots of handy other assertions that you can leverage to write better tests. Including calledWith, calledWithMatch, and calledWithExactly.