Using Mocha, I am attempting to test whether a constructor throws an error. I haven't been able to do this using the expect syntax, so I'd like to do the following:
it('should throw exception when instantiated', function() {
try {
new ErrorThrowingObject();
// Force the test to fail since error wasn't thrown
}
catch (error) {
// Constructor threw Error, so test succeeded.
}
}
Is this possible?
You can try using Chai's
throw
construct. For example:2017 answer if you need to do this with async code: using await and not needing any other libraries.
Note the poster was only doing sync code, but I expect a lot of people using async were led here by the question title!
Chai now has
should.fail()
andexpect.fail()
https://github.com/chaijs/chai/releases/tag/2.1.0
If you don't want to wrap a whole lot of source into the
expect
parameter, or if you have many arguments to pass and it just gets ugly, you can still do this with the original syntax just fine by leveraging thedone
argument that is provided (but was originally ignored):Because you're using
done
here, it allows you go execute arbitrary code above it in thetry
, then specify exactly where in your source you'd like to record the failure.Normally, someone may be tempted to
throw
orassert(false)
, but these will both be caught by thecatch
of thetry
, and cause you to do some meta-checking to determine if the error you caught was the expected error from your test, or if it was the final determination that your test failed. That's just a mess.Mocha in default is using Assert from node.js (https://nodejs.org/api/assert.html). You don't need any external libraries to check if a method throws an error.
Assert has a method -
assert.throws
, it has three parameters, but only two really matters here:Let's imagine that you have a function called
sendMessage(message)
which throws an error when message parameter is not set. Function code:Ok, so in order to test it, you need additional function to cover input. Why? Because
assert.throws
doesn't give any opportunity to pass parameters to the function which going to be tested.So instead of
you need to create anonymous function:
Can you see the difference? Instead of passing function directly, I have put the function call inside anonymous function, in purpose of calling it with a prepared input.
What about the second parameter. It depends from what kind of error should be thrown, in above example
Error
object was thrown, so I had to put thereError
. In result of this action,assert.throws
compares if thrown object is object of the same type. If instead ofError
something different will be thrown, then this part needs to be changed. For example instead ofError
I will throw a value of typeString
.Now the test call
Instead of
Error
in second parameter I have used the comparison function in order to compare thrown error with the expectation.If you are using should.js you can do
(new ErrorThrowingObject).should.throw('Option Error Text or Regular Expression here')
If you don't want to should a separate library, you could also do something like this:
This way, you know the error is caught if the test finishes. Otherwise, you will get a timeout error.