Testing for errors thrown in Mocha

116,074

Solution 1

You're not passing your function to assert.throws() the right way.

The assert.throws() function expects a function as its first parameter. In your code, you are invoking iThrowError and passing its return value when calling assert.throws().

Basically, changing this:

assert.throws(iThrowError(), Error, "Error thrown");

to this:

assert.throws(iThrowError, Error, "Error thrown");

should solve your problem.

With args:

assert.throws(() => { iThrowError(args) }, Error);

or

assert.throws(function() { iThrowError(args) }, Error, /Error thrown/);

Solution 2

Adding to the top answer, if you need to invoke your function as part of the test (i.e. your function should only throw an error if certain parameters are passed), you can wrap your function call in an anonymous function, or, in ES6+, you can pass your function in an arrow function expression.

// Function invoked with parameter.
// TEST FAILS. DO NOT USE.
assert.throws(iThrowError(badParam), Error, "Error thrown"); // WRONG!

// Function invoked with parameter; wrapped in anonymous function for test.
// TEST PASSES.
assert.throws(function () { iThrowError(badParam) }, Error, "Error thrown");

// Function invoked with parameter, passed as predicate of ES6 arrow function.
// TEST PASSES.
assert.throws(() => iThrowError(badParam), Error, "Error thrown");

And, just for the sake of thoroughness, here's a more literal version:

// Explicit throw statement as parameter. (This isn't even valid JavaScript.)
// TEST SUITE WILL FAIL TO LOAD. DO NOT USE, EVER.
assert.throws(throw new Error("Error thrown"), Error, "Error thrown"); // VERY WRONG!

// Explicit throw statement wrapped in anonymous function.
// TEST PASSES.
assert.throws(function () { throw new Error("Error thrown") }, Error, "Error thrown");

// ES6 function. (You still need the brackets around the throw statement.)
// TEST PASSES.
assert.throws(() => { throw new Error("Error thrown") }, Error, "Error thrown");

Solution 3

I saw you were able to resolve your problem but were not able to check for a specific error. To do so using Chai's expect/should syntax, you can use the parameters from the different signatures of throw():

@param{ ErrorConstructor } constructor
@param{ String | RegExp } expectederror message
@param{ String } message _optional_

In your example, you should be able to use either of the following:

expect(iThrowError).to.throw(/Error thrown/);
expect(iThrowError).to.throw(Error, /Error thrown/);
expect(iThrowError).to.throw(new Error('Error thrown'));

And (again, from chai's documentation), you could filter other error messages using:

expect(iThrowError).to.throw(Error).and.not.throw(/Another Error thrown/);

Hope this helps!

Share:
116,074

Related videos on Youtube

Chris Neitzer
Author by

Chris Neitzer

Updated on November 13, 2021

Comments

  • Chris Neitzer
    Chris Neitzer over 2 years

    I'm hoping to find some help with this problem. I'm trying to write tests for an application I am writing. I have distilled the problem in to the following sample code. I want to test that an error was thrown. I'm using Testacular as a test runner with mocha as the framework and chai as the assertion library. The tests run, but the test fails because an error was thrown! Any help is greatly appreciated!

    function iThrowError() {
        throw new Error("Error thrown");
    }
    
    var assert = chai.assert,
        expect = chai.expect;
    describe('The app', function() {
        describe('this feature', function() {
            it("is a function", function(){
                assert.throw(iThrowError(), Error, "Error thrown");
            });
        });
    });
    
    • Chris Neitzer
      Chris Neitzer about 11 years
      Well, I figured out that if I change the assertion from assert.throw(iThrowError(), Error, "Error thrown"); to expect(iThrowError).to.throw(); This makes the test pass, but it does not seem to allow for checking if any specific error, which I think would be more useful. I think I am missing something still.
  • Glen Selle
    Glen Selle over 10 years
    What if I wanted to pass a parameter to the function? Is there a way to do that?
  • Marc Gibbons
    Marc Gibbons about 10 years
    Glen, to pass parameters to your function, try wrapping in a function: assert.throw(function() { iThrowError(args) }, Error)
  • jaseeey
    jaseeey over 7 years
    I had a similar problem using Chai expect, where I was actually calling the function rather than passing the reference. This solution fixed the problem, thanks!
  • Louis
    Louis over 7 years
    What's the point of repeating the accepted answer?
  • Jake
    Jake over 7 years
    @Louis This is not a repeat. The accepted answer is to pass the function as a reference, and to not invoke the function. As I state at the top of my answer, I'm explaining how to actually invoke the function as part of the test if the test needs the invocation.
  • JoeKir
    JoeKir over 7 years
    @GlenSelle I used bind to do this. e.g. ``` function print(input){ console.log(input) }; var foo = print.bind(undefined,"my string"); foo() // prints "my string" ``` developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • Boogie
    Boogie over 2 years
    You have a typo in your last 2 code sentences. It should be assert.throws. instead of assert.throw So the correct code would be: assert.throws(() => { iThrowError(args) }, Error); assert.throws(function() { iThrowError(args) }, Error, /Error thrown/);
  • Steve Chambers
    Steve Chambers over 2 years
    Fixed the above ^
  • adriaan
    adriaan over 2 years
    If you don't use Chai and just Mocha, change it to assert.throws(() => iThrowError(args), { name: 'Error', message: 'Error thrown' }); Mocha does uses the Node.js Assert library.