Catching thrown errors with SinonJS
Solution 1
It appears that this works inside a try
/catch
:
function foo() { throw new Error("hey!"); }
var fooSpy = sinon.spy(foo);
try {
fooSpy();
} catch (e) {
// pass
}
assert(fooSpy.threw());
Note that you have to call fooSpy
, not foo
itself.
But also note that .should.be.true()
is not part of Sinon, so you're probably already using Chai or a similar library, in which case the expect(foo).to.have.thrown()
or assert.throws(foo, someError)
syntax seems much nicer.
Update: If you're using ShouldJS, looks like you can use should.throws
. I still think this is nicer than using the Sinon version for this purpose.
Solution 2
Revised
Following @nrabinowitz's helpful advice, here's a solution that uses should.throws
. This avoids using Sinon.spy
altogether.
describe('#testError', function() {
it('throws an error', function() {
should.throws(function() {
testError(false);
});
});
});
Related videos on Youtube
benjarwar
I'm a jack of several trades. A coder by day, musician/artist by night. I like making useful things as much as useless things. You can find me on the Twitter, the Instagram, the LinkedIn.
Updated on June 04, 2022Comments
-
benjarwar almost 2 years
I've got a method that may throw an Error, but I'm having trouble writing a SinonJS/Mocha/Should unit test case for this condition.
Sample function under test:
function testError(value) { if (!value) { throw new Error('No value'); return false; } };
Sample test:
describe('#testError', function() { it('throws an error', function() { var spy = sinon.spy(testError); testError(false); spy.threw().should.be.true(); }); });
This outputs:
#testError 1) throws an error 0 passing (11ms) 1 failing 1) #testError throws an error: Error: No value at testError (tests/unit/js/test-error.js:6:14) at Context.<anonymous> (tests/unit/js/test-error.js:14:6)
I was expecting Sinon to catch the Error and allow me to spy on the throw, but it seems to fail the test instead. Any ideas?
I referred to Don't sinon.js spys catch errors? but the only solution there is to use
expect
. I'd prefer to keep with a single assertion library if possible. -
nrabinowitz over 8 yearsThat doesn't do what you think.
stub.throws()
is pre-programming behavior for the stub, not asserting that it was called. Stubs do not call the underlying function - try this out with another function that does not throw, and you'll see the behavior unchanged. -
benjarwar over 8 yearsAh, you're right. Using
stub
was a false positive. I think usingshould.throws
and calling the actual function under test works. And avoids using Sinon entirely. See my revised answer. -
benjarwar over 8 yearsThanks, @nrabinowitz. Looks like
should.throws
might be the ticket. See my revised answer below.