Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test async function to throw with mocha

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?

like image 288
kentor Avatar asked Apr 22 '18 20:04

kentor


People also ask

How do you test async Mocha?

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); });

How do you use async await in Mocha?

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.

What is Mocha and Chai testing?

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.


1 Answers

.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;
like image 76
Estus Flask Avatar answered Sep 28 '22 06:09

Estus Flask