'Jest - Warning: You called act(async () => ...) without await
I have a test where I'm trying to test a component's default render compared to a render when something (in this case a 0) is in storage. The component should render the same in both cases. To test this, I need to render the component twice.
import { render, waitFor } from "@testing-library/react-native";
import * as React from "react";
import { View } from "react-native";
it("Shouldn't break when rendering twice...", async () => {
const firstRender = await waitFor(() => render(<View />));
const defaultJson = JSON.stringify(firstRender.toJSON());
firstRender.unmount();
putTheThingInAsyncStorage();
const secondRender = await waitFor(() => render(<View />));
const newJson = JSON.stringify(secondRender.toJSON());
expect(newJson).toBe(defaultJson);
// In this particular test case, they should be the same.
expect(newJson).toBe(defaultJson);
removeTheThingFromAsyncStorage();
});
This test works, but the console gives me this nagging warning: Warning: You called act(async () => ...) without await. This could lead to unexpected testing behaviour, interleaving multiple act calls and mixing their scopes. You should - await act(async () => ...);
Because of this, I've added the await waitFor(...); to the render calls, but I still get the warning. At this point, the warning is lying to me because I am, in fact, using the await keyword so I'm not sure what the issue is.
What am I doing wrong?
Solution 1:[1]
It's still confusing to me that I was getting the specific warnings that I was getting, but here's what seemed to work for me:
import { render, waitFor } from "@testing-library/react-native";
import * as React from "react";
import { View } from "react-native";
it("Shouldn't break when rendering twice...", async () => {
// DO NOT use await or put render() in a waitFor
const firstRender = render(<View/>);
const defaultJson = JSON.stringify(firstRender.toJSON());
act(() => {
// Unmount should be wrapped in an act, but don't use await
firstRender.unmount();
});
putTheThingInAsyncStorage();
// DO NOT use await or put render() in a waitFor
const secondRender = render(<View/>);
// I did need to use await and waitFor for this toJSON()
await waitFor(() => secondRender.toJSON());
const newJson = JSON.stringify(secondRender.toJSON());
expect(newJson).toBe(defaultJson);
removeTheThingFromAsyncStorage();
});
Solution 2:[2]
This question has been debated a lot here: https://github.com/callstack/react-native-testing-library/issues/379
Here is my solution:
Create test/asap.js with
const nodePromise = Promise;
module.exports = (r) => nodePromise.resolve().then(r);
Then add to jest.config.js:
moduleNameMapper: {
'^asap\/+.*$': '<rootDir>/test/asap.js',
}
This will short-circuit the asap module which is used by the internal Promise shim of react-native and is not needed for the jest environment.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Austin Brown |
| Solution 2 | mmomtchev |
