I've got an async function which runs 2000ms and then it'll throw an exception. I am trying to test exactly this behaviour with Mocha / chai, but apparently I am doing it wrong.
That's what I've tried:
First:
expect(publisher.dispatchMessage<ExampleResponseMessage>(message, {}, 2 * 1000)).to.eventually.throw();
This marks the test as passed (52ms runtime) but throws an exception 2s later. So apparently it hasn't awaited the promise of that function at all.
Second:
expect(async () => {
await publisher.dispatchMessage<ExampleResponseMessage>(message, {}, 2 * 1000);
}).to.throw();
The test fails with: should reject a scheduled message after a predefined timeout: AssertionError: expected [Function] to throw an error at Context.mocha_1.it (test\integration\rpc-communication.spec.ts:75:16) at
Expected behaviour is that the test passed because an exception is thrown after 2000ms, which is within the given test case timeout of 4000ms.
Additional information:
This would work. The promise is rejected with an error (I can also change it to reject with a string). That should proove that dispatchMessage() is working as intended. The test case takes 2002ms and passes then.
try {
await publisher.dispatchMessage<ExampleResponseMessage>(message, {}, 2 * 1000);
} catch (err) {
expect(err).to.be.an('Error');
}
Question:
How do I properly test if an async function throws an exception?
Writing Asynchronous Tests with Mocha. To indicate that a test is asynchronous in Mocha, you simply pass a callback as the first argument to the it() method: it('should be asynchronous', function(done) { setTimeout(function() { done(); }, 500); });
To use the newer async/await syntax with Mocha, all you have to do is ensure that your it method has the async keyword, and instead of returning your promise, you just add an await keyword before your async function.
Introduction to Unit Testing with Mocha and Chai Mocha is a widely used JavaScript test framework running on NodeJS and browsers. It supports asynchronous testing running the tests serially, allowing for more flexible and accurate reporting.
.to.throw()
shouldn't work on async
function because it doesn't throw an error, it returns rejected promise.
The problem is specific to chai-as-promised. As explained in this issue, .to.eventually.throw()
won't work as expected. It asserts that a promise resolves with a function that will throw error synchronously when called. This is likely not what happens in dispatchMessage
.
This depends on dispatchMessage
but likely should be:
expect(publisher.dispatchMessage<ExampleResponseMessage>(message, {}, 2 * 1000))
.to.be.rejected;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With