Hey DEV community, I'm struggling with why the react-dom
library is yelling at me in my tests. So much so, that I spun up a git repo in order to demonstrate what the issue is that I'm facing.
If you pull down the repo, you can see the console warning, even though I'm getting passing tests.
Quick overview of the test:
- Wrap a component in a
- Provide the MockedProvider with a mock query/response
- Mount said component via enzyme
- await the data to refresh and run my assertions
Every time that I run the tests, I get the following console warning, in bright red colors:
Warning: An update to Query inside a test was not wrapped in act(...).
When testing, code that causes React state updates should be wrapped into act(...):
act(() => {
/* fire events that update state */
});
/* assert on the output */
This ensures that you're testing the behavior the user would see in the browser. Learn more at https://fb.me/react-wrap-tests-with-act
in Query (at App.tsx:37)
in div (at App.tsx:36)
in App (at App.test.tsx:51)
in ApolloProvider (created by MockedProvider)
in MockedProvider (created by WrapperComponent)
in WrapperComponent
I even followed the link and used the act()
function referenced. I actually left that third test in there, because it throws the same warning.
So, is it that I'm using Enzyme to mount instead of React Test Renderer? Anybody have some tips? I'm open to pull requests with best practices for testing.
Top comments (4)
Hi there!
waitForExpect
is not wrapping your callback withact
(like it should in react), thus causing that error.My recommendation would be to use
@testing-library/react
wait
function.This approach should make your second and third test warnings go away.
As for the first test (which also throws this warning)
So what actually happens? Well, you make an assertion for loading state which passes, then, very loosely named, next tick happens and state updates to an error (asynchronously) and the test finishes. What you have to do in such situations is to queue a task (task-queue) that contains an act, after the assertion, like so:
The error will go await.
act
will put your callback inside batch update when React flushes tasks, guaranteeing that any left-overs async updates are taken care of.You should give
@testing-library/react
a shot! in my opinion, it's much better thanenzyme
.I'm not an expert and the things I said about the task queue and stuff may be wrong. It's just how I think about it.
Cheers!
Thanks for the tip, Wojciech.
I looked into the library you referenced for a few minutes and found that
@testing-library/react
has await()
function, which is documented as a small wrapper around the await-for expect module.I don't think that is much gained from using it. There's even a callout in the readme about suppressing the very warning that I'm complaining about.
Wojciech, if I'm following your notes correctly, the difference is in how the
testing-library/react
appends to the action queue the callback versus howwait-for-expect
isn't allowing the other asynchronous tasks to complete.Sorry for being stubborn before, the event loop is still a new concept to me. Thanks for the overall help. I was able to put together a simple commit that swaps the libraries and gets me to a more green test suite.
Thanks again for the updated response.
I'll go back through and update my tests to try following this pattern. Will update when I have some new findings.