I want to take advantage of Mocha's built in promise support, but i'm having difficulty dealing with false positives when I want to test catch
branches in my promise chains.
This question gets closest to what I want, but the solution requires every developer on my project to add a then
that will throw an error, and ensure that that error doesn't accidentally pass the test.
Because of this, i've had to revert to using the done
style of tests, which relies on the built in timeout to catch errors instead of an assertion. This is less than ideal, but removes the chance of false positives.
var RSVP = require('RSVP');
function request (shouldSucceed) {
if (shouldSucceed) {
return RSVP.Promise.resolve('success');
} else {
return RSVP.Promise.reject(new Error('failure'));
}
}
describe('request', function () {
it('throws an error if shouldSucceed is not provided', function () {
// this test is incorrectly calling `request`
// which leads to it passing without actually testing
// the behaviour it wants to
return request(true)
.catch(function (err) {
expect(err).to.be.an.instanceof(Error)
});
});
it('throws an error if shouldSucced is not provided (manual then block)', function () {
// this test tacks a `then` onto the chain, to ensure `request`
// actually throws an error as expected
// unfortunately, it still passes since the assertion needs to do
// a little extra work to ensure the type of error thrown is the
// expected error
return request(true)
.then(function () {
throw new Error('Not expected');
})
.catch(function (err) {
expect(err).to.be.an.instanceof(Error)
});
});
it('throws an error if shouldSucceed is not provided (done syntax)', function (done) {
// this assertion fails (as it should)
// due to a timeout
return request(true)
.catch(function () {
expect(err).to.be.an.instanceof(Error);
done()
});
});
});
Output:
request
✓ throws an error if shouldSucceed is not provided
✓ throws an error if shouldSucced is not provided (manual then block)
1) throws an error if shouldSucceed is not provided (done syntax)
2 passing (2s)
1 failing
1) request throws an error if shouldSucceed is not provided (done syntax):
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.
Is there a cleaner way to tell mocha that I am expecting something to happen in a catch
block, and that a successful resolution of the promise should be a test failure?