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:
<MarkJ's accepted answer is the way to go and way simpler than others here. Let me show example in real world:
function fn(arg) {
if (typeof arg !== 'string')
throw TypeError('Must be an string')
return { arg: arg }
}
describe('#fn', function () {
it('empty arg throw error', function () {
expect(function () {
new fn()
}).to.throw(TypeError)
})
it('non-string arg throw error', function () {
expect(function () {
new fn(2)
}).to.throw(TypeError)
})
it('string arg return instance { arg: <arg> }', function () {
expect(new fn('str').arg).to.be.equal('str')
})
})
Using the should.js library with should.fail
var should = require('should')
it('should fail', function(done) {
try {
new ErrorThrowingObject();
// Force the test to fail since error wasn't thrown
should.fail('no error was thrown when it should have been')
}
catch (error) {
// Constructor threw Error, so test succeeded.
done();
}
});
Alternative you can use the should throwError
(function(){
throw new Error('failed to baz');
}).should.throwError(/^fail.*/)
And with chai using the throw api
var expect = require('chai').expect
it('should fail', function(done) {
function throwsWithNoArgs() {
var args {} // optional arguments here
new ErrorThrowingObject(args)
}
expect(throwsWithNoArgs).to.throw
done()
});
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:
function sendMessage(message) {
if (!message || typeof message !== 'string') {
throw new Error('Wrong message');
}
// rest of function
}
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
// WRONG
assert.throws(sendMessage, Error); // THIS IS WRONG! NO POSSIBILITY TO PASS ANYTHING
you need to create anonymous function:
// CORRECT
assert.throws(() => {
sendMessage(12); // usage of wanted function with test parameters
}, Error)
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 there Error
. In result of this action, assert.throws
compares if thrown object is object of the same type. If instead of Error
something different will be thrown, then this part needs to be changed. For example instead of Error
I will throw a value of type String
.
function sendMessage(message) {
if (!message || typeof message !== 'string') {
throw 'Wrong message'; // change to String
}
// rest of function
}
Now the test call
assert.throws(() => {
sendMessage(12); // usage of wanted function with test parameters
}, (err) => err === 'Wrong message')
Instead of Error
in second parameter I have used the comparison function in order to compare thrown error with the expectation.