GilZ
GilZ

Reputation: 6477

Async test with inner async function should fail

In my mocha.js test, I'm calling an async function that throws an error, but the test doesn't fail. It passes and there is an UnhandledPromiseRejectionWarning:

describe('async function', async function () {
    it('should fail', async function () {
        [1].forEach(async function () {
            throw new Error("Why can't I see this error?!");
        });
    });
});

Note, that a simpler case works as expected:

describe('async function', async function () {
    it('should fail', async function () {
        throw new Error('This one fails the test');
    });
});

How can I cause the test to fail due to an exception in an inner function?

(I've tried adding an unhandledRejection handler, but the test still passes)

Upvotes: 0

Views: 446

Answers (2)

Felix Kling
Felix Kling

Reputation: 816910

Louis' answer is spot on. As an alternative, you could avoid using an inner function and use a normal for loop instead:

const data = [1];
for (let i = 0; i < data.length; i++) {
  // await some more stuff here
  throw new Error('This one fails the test');
}

Upvotes: 3

Louis
Louis

Reputation: 151491

Your test case with .forEach cannot work like you want it to work. When it calls its async callback, the callback does create a promise, but .forEach does not do anything with it. The callback you pass to it is async too and it does return a promise, but the promise it returns is not connected to the promises that the callback to .forEach produces. That's why you get UnhandledPromiseRejectionWarning.

You can solve the issue by connecting the promises through Promise.all:

describe('async function', async function () {
    it('should fail', async function () {
        return Promise.all([1].map(async function () {
            throw new Error("Why can't I see this error?!");
        }));
    });
});

Using map makes it so that your array is turned into an array of promises, and then Promise.all waits for all the promises in the array to be resolved, or it rejects if any promise rejects. Returning the return value of the Promise.all call then allow Mocha to wait for the whole thing.

Upvotes: 3

Related Questions