Catching thrown errors with SinonJS

15,686

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);
    });
  });
});
Share:
15,686

Related videos on Youtube

benjarwar
Author by

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, 2022

Comments

  • benjarwar
    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
    nrabinowitz over 8 years
    That 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
    benjarwar over 8 years
    Ah, you're right. Using stub was a false positive. I think using should.throws and calling the actual function under test works. And avoids using Sinon entirely. See my revised answer.
  • benjarwar
    benjarwar over 8 years
    Thanks, @nrabinowitz. Looks like should.throws might be the ticket. See my revised answer below.