Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Necessary to use expect.assertions() if you're awaiting any async function calls?

Tags:

jestjs

I've found a lot of this sort of thing when refactoring our Jest test suites:

it('calls the API and throws an error', async () => {   expect.assertions(2);   try {     await login('email', 'password');   } catch (error) {     expect(error.name).toEqual('Unauthorized');     expect(error.status).toEqual(401);   } }); 

I believe the expect.assertions(2) line is redundant here, and can safely be removed, because we already await the async call to login().

Am I correct, or have I misunderstood how expect.assertions works?

like image 977
callum Avatar asked Jun 12 '18 11:06

callum


People also ask

What is expect assertion?

Expect. assertions(number) verifies that a certain number of assertions are called during a test. This is often useful when testing asynchronous code, in order to make sure that assertions in a callback actually got called. So to put in other words, expect.

What is expect in Jest?

When you're writing tests, you often need to check that values meet certain conditions. expect gives you access to a number of "matchers" that let you validate different things. For additional Jest matchers maintained by the Jest Community check out jest-extended .

How do you resolve a promise in Jest?

You can also use the . resolves matcher in your expect statement, and Jest will wait for that promise to resolve. If the promise is rejected, the test will automatically fail. return expect(fetchData()).

Which assertion used to test a value is with exact equality in Jest?

Jest documentation reads: toBe just checks that a value is what you expect. It uses === to check strict equality.


2 Answers

expect.assertions is important when testing the error scenarios of asynchronous code, and is not redundant.

If you remove expect.assertions from your example you can't be confident that login did in fact throw the error.

it('calls the API and throws an error', async () => {   try {     await login('email', 'password');   } catch (error) {     expect(error.name).toEqual('Unauthorized');     expect(error.status).toEqual(401);   } }); 

Let's say someone changes the behavior of login to throw an error based on some other logic, or someone has affected the mock for this test which no longer causes login to throw. The assertions in the catch block won't run but the test will still pass.

Using expect.assertions at the start of the test ensures that if the assertions inside the catch don't run, we get a failure.

like image 108
user195257 Avatar answered Oct 07 '22 04:10

user195257


This is from Jest documentation:

Expect.assertions(number) verifies that a certain number of assertions are called during a test. This is often useful when testing asynchronous code, in order to make sure that assertions in a callback actually got called.

So to put in other words, expect.assertions makes sure that the n number of assertions are made by the end of the test.

It's good to use it especially when writing a new tests, so one can easily check that correct assertions are made during the test. Async tests often pass because the intended assertions were not made before the test-runner (Jest,Mocha etc.) thought the test was finished.

like image 37
Moyote Avatar answered Oct 07 '22 06:10

Moyote