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:
<2017 answer if you need to do this with async code: using await and not needing any other libraries.
it('Returns a correct error response when making a broken order', async function(){
this.timeout(5 * 1000);
var badOrder = {}
try {
var result = await foo.newOrder(badOrder)
// The line will only be hit if no error is thrown above!
throw new Error(`Expected an error and didn't get one!`)
} catch(err) {
var expected = `Missing required field`
assert.equal(err.message, expected)
}
});
Note the poster was only doing sync code, but I expect a lot of people using async were led here by the question title!
With Chai throw
(ES2016)
http://chaijs.com/api/bdd/#method_throw
For clarity... This works
it('Should fail if ...', done => {
let ret = () => {
MyModule.myFunction(myArg);
};
expect(ret).to.throw();
done();
});
This doesn't work
it('Should fail if ...', done => {
let ret = MyModule.myFunction(myArg);
expect(ret).to.throw();
done();
});
Chai now has
should.fail()
and expect.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 the done
argument that is provided (but was originally ignored):
it('should throw exception when instantiated', function(done: Done) {
try {
new ErrorThrowingObject();
done(new Error(`Force the test to fail since error wasn't thrown`));
}
catch (error) {
// Constructor threw Error, so test succeeded.
done();
}
}
Because you're using done
here, it allows you go execute arbitrary code above it in the try
, then specify exactly where in your source you'd like to record the failure.
Normally, someone may be tempted to throw
or assert(false)
, but these will both be caught by the catch
of the try
, 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.
You can try using Chai's throw
construct. For example:
expect(Constructor).to.throw(Error);
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:
it('should do whatever', function(done) {
try {
...
} catch(error) {
done();
}
}
This way, you know the error is caught if the test finishes. Otherwise, you will get a timeout error.