Can you write async tests that expect toThrow?

JavascriptJestjs

Javascript Problem Overview


I'm writing an async test that expects the async function to throw like this:

it("expects to have failed", async () => {
  let getBadResults = async () => {
    await failingAsyncTest()
  }
  expect(await getBadResults()).toThrow()
})

But jest is just failing instead of passing the test:

 FAIL  src/failing-test.spec.js
  ● expects to have failed

    Failed: I should fail!

If I rewrite the test to looks like this:

expect(async () => {
  await failingAsyncTest()
}).toThrow()

I get this error instead of a passing test:

expect(function).toThrow(undefined)

Expected the function to throw an error.
But it didn't throw anything.

Javascript Solutions


Solution 1 - Javascript

You can test your async function like this:

it('should test async errors', async () =>  {        
    await expect(failingAsyncTest())
    .rejects
    .toThrow('I should fail');
});

'I should fail' string will match any part of the error thrown.

Solution 2 - Javascript

I'd like to just add on to this and say that the function you're testing must throw an actual Error object throw new Error(...). Jest does not seem to recognize if you just throw an expression like throw 'An error occurred!'.

Solution 3 - Javascript

await expect(async () => { 
    await someAsyncFunction(someParams); 
}).rejects.toThrowError("Some error message");

We must wrap the code in a function to catch the error. Here we are expecting the Error message thrown from someAsyncFunction should be equal to "Some error message". We can call the exception handler also

await expect(async () => { 
    await someAsyncFunction(someParams); 
}).rejects.toThrowError(new InvalidArgumentError("Some error message"));

Read more https://jestjs.io/docs/expect#tothrowerror

Solution 4 - Javascript

Custom Error Class

The use of rejects.toThrow will not work for you. Instead, you can combine the rejects method with the toBeInstanceOf matcher to match the custom error that has been thrown.

Example

it("should test async errors", async () => {
  await expect(asyncFunctionWithCustomError()).rejects.toBeInstanceOf(
    CustomError
  )
})

or


it("should test async errors", async () => {
  await expect(async () => {
    await asyncFunctionWithCustomError()
  }).rejects.toBeInstanceOf(CustomError)
})

Solution 5 - Javascript

I've been testing for Firebase cloud functions and this is what I came up with:

test("It should test async on failing cloud functions calls", async () => {
    await expect(async ()=> {
        await failingCloudFunction(params)
    })
    .rejects
    .toThrow("Invalid type"); // This is the value for my specific error
  });

This is built on top of lisandro's answer.

Solution 6 - Javascript

To be able to make many tests conditions without having to resolve the promise every time, this will also work:

it('throws an error when it is not possible to create an user', async () => {
        const throwingFunction = () => createUser(createUserPayload)

        // This is what prevents the test to succeed when the promise is resolved and not rejected
        expect.assertions(3)

        await throwingFunction().catch(error => {
            expect(error).toBeInstanceOf(Error)
            expect(error.message).toMatch(new RegExp('Could not create user'))
            expect(error).toMatchObject({
                details: new RegExp('Invalid payload provided'),
            })
        })
    })

Solution 7 - Javascript

This worked for me

it("expects to have failed", async () => {
  let getBadResults = async () => {
    await failingAsyncTest()
  }
  expect(getBadResults()).reject.toMatch('foo')
  // or in my case
  expect(getBadResults()).reject.toMatchObject({ message: 'foo' })
})

Solution 8 - Javascript

test("It should test async on failing cloud functions calls", async () => {
   failingCloudFunction(params).catch(e => {
    expect(e.message).toBe('Invalid type')
   })
  });

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSeanView Question on Stackoverflow
Solution 1 - JavascriptLisandroView Answer on Stackoverflow
Solution 2 - JavascriptSteveView Answer on Stackoverflow
Solution 3 - JavascriptSumit BopcheView Answer on Stackoverflow
Solution 4 - JavascriptLaode Muhammad Al FatihView Answer on Stackoverflow
Solution 5 - JavascriptJuan GiacosaView Answer on Stackoverflow
Solution 6 - JavascriptJonas BragaView Answer on Stackoverflow
Solution 7 - JavascriptGünter ZöchbauerView Answer on Stackoverflow
Solution 8 - JavascriptPeter AkinloluView Answer on Stackoverflow