I'm struggling to work out the best way to verify that a promise is rejected in a Mocha test while using async/await.
Here's an example that works, but I dislike that should.be.rejectedWith
returns a promise that needs to be returned from the test function to be evaluated properly. Using async/await removes this requirement for testing values (as I do for the result of wins()
below), and I feel that it is likely that I will forget the return statement at some point, in which case the test will always pass.
// Always succeeds
function wins() {
return new Promise(function(resolve, reject) {
resolve('Winner');
});
}
// Always fails with an error
function fails() {
return new Promise(function(resolve, reject) {
reject('Contrived Error');
});
}
it('throws an error', async () => {
let r = await wins();
r.should.equal('Winner');
return fails().should.be.rejectedWith('Contrived Error');
});
It feels like it should be possible to use the fact that async/await translates rejections to exceptions and combine that with Chai's should.throw, but I haven't been able to determine the correct syntax.
Ideally this would work, but does not seem to:
it('throws an error', async () => {
let r = await wins();
r.should.equal('Winner');
(await fails()).should.throw(Error);
});
The problem with this approach is that
(await fails()).should.throw(Error)
doesn't make sense.await
resolves aPromise
. If thePromise
rejects, it throws the rejected value.So
(await fails()).should.throw(Error)
can never work: iffails()
rejects, an error is thrown, and.should.throw(Error)
is never executed.The most idiomatic option you have is to use Chai's
rejectedWith
property, as you have shown in your question.Here's a quick example. Not much is different from what you've demonstrated in your question; I'm just using
async
functions forwins()
andfails()
andexpect
instead ofshould
. Of course, you can use functions that return aPromise
andchai.should
just fine.If you like want your
wins()
test to resemble yourfails()
test more closely, you can write yourwins()
test like so:The key thing to remember in either of these examples is that
chai-as-promised
returns promises for its functions such asrejectedWith
andeventually.something
. Therefore you mustawait
them in the context of anasync
test function, or else failing conditions will still pass:If you ran the tests with the code above, you'd get the following:
As you can see, the chai assertions actually failed, but they were failed in the context of a Promise that no one ever
await
ed orcatch
ed. So Mocha sees no failure and marks the tests as though they passed, but Node.js (in behaviour that will change in the future as noted above) prints the unhandled rejections to the terminal.This is my Solution for the problem .