38

Given this code:

var assert = require('assert');

function boom(){
    throw new Error('BOOM');
}

assert.throws( boom(), Error );

I get this output, with node 0.4.9:

node.js:134
        throw e; // process.nextTick error, or 'error' event on first tick
        ^
Error: BOOM
    at boom ([EDITED]/assert.throws.test.js:4:9)
    at Object.<anonymous> ([EDITED]/assert.throws.test.js:7:17)
    at Module._compile (module.js:402:26)
    at Object..js (module.js:408:10)
    at Module.load (module.js:334:31)
    at Function._load (module.js:293:12)
    at Array.<anonymous> (module.js:421:10)
    at EventEmitter._tickCallback (node.js:126:26)

This, to me, implies that an uncaught exception has occurred, as opposed to a reported, caught exception. Looking in the docs, I notice that the examples look more like this:

var assert = require('assert');

function boom(){
    throw new Error('BOOM');
}

assert.throws( boom, Error );

But how do you test if it throws an exception given a certain input? For example:

var assert = require('assert');

function boom(blowup){
    if(blowup)
        throw new Error('BOOM');
}

assert.throws( boom, Error );

This will fail. What am I doing wrong, or what secret does everybody know but me?

Ryan Schumacher
  • 1,816
  • 2
  • 21
  • 33
Andrew
  • 3,332
  • 4
  • 31
  • 37

4 Answers4

73

The examples take a function, while your sample code calls a function and passes the result. The exception happens before the assert even gets to look at it.

Change your code to this:

var assert = require('assert');

function boom(){
    throw new Error('BOOM');
}

assert.throws( boom, Error ); // note no parentheses

EDIT: To pass parameters, just make another function. After all, this is javascript!

var assert = require('assert');

function boom(blowup){
    if(blowup)
        throw new Error('BOOM');
}

assert.throws( function() { boom(true); }, Error );
Mike Caron
  • 14,351
  • 4
  • 49
  • 77
  • This is what my second example demonstrates. This makes sense, because it needs to call the test function in a controlled environment. But what if the function requires input to throw an exception, like my third example? – Andrew Jul 11 '11 at 03:56
  • Well, just do what javascript is good at: creating new functions, as in my edit – Mike Caron Jul 11 '11 at 03:59
  • Thank you so much for mentioning the use of additional parameters. This was a difficult detail to find out about. Probably wouldn't have tried it and looked for another way, so thank you again. – Brandon Clark Mar 25 '16 at 21:27
  • I had the exact same root cause in a completely different area (postman script) so thanks for making me spot it – MattH Feb 16 '19 at 18:40
10

You can use bind():

assert.throws( boom.bind(null), Error );

With arguments it is:

assert.throws( boom.bind(null, "This is a blowup"), Error );
Kiechlus
  • 1,167
  • 12
  • 21
7

Current node stable (v4.1) includes fat arrow function support by default (no --harmony flag required) so you can do something like:

assert.throws(()=>boom(), Error);
assert.throws(()=>boom(true), Error); // with params

Even if you have parentheses after boom() (so you're actually invoking it, instead of passing a reference to the function object), by using the fat arrow function you're wrapping it in a block, which is what assert.throws expects.

Mihai Rotaru
  • 1,953
  • 3
  • 26
  • 28
0

This is closely related to the issue people with with other assertion Mocha/Chai. See this answer for the description with node examples:
Mocha / Chai expect.to.throw not catching thrown errors

Community
  • 1
  • 1
Charles Merriam
  • 19,908
  • 6
  • 73
  • 83