In my simple React/ReactDOM/Enzyme unit test I get a warning from ReactDOM about wrapping any mutations to state in act()
. Why do I need to do this if my test passes anyway? I have 50 or so React components that all use hooks, custom hooks, etc. and I never wrap in act()
and they all pass.
Can I just disable this warning? I don't want to add extra code for what appears to be no reason.
The warning:
Warning: An update to MyComponent 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 [redacted]
My test:
const App = () => {
const [isLoaded, setIsLoaded] = useState(false);
const myOnClick = () => {
setIsLoaded(true);
};
return (
<div onClick={myOnClick}>
{isLoaded ? 'Yes' : 'No'}
</div>
)
}
describe('My test', () => {
let wrapper
beforeAll(() => {
wrapper = mount(<App />)
})
it('renders "no"', () => {
expect(wrapper.text()).toBe('No')
})
describe('When onClick is called', () => {
beforeAll(() => {
wrapper.find('div').prop('onClick')()
})
it('renders "yes"', () => {
expect(wrapper.text()).toBe('Yes')
})
})
})
CodeSandbox repro: https://codesandbox.io/s/react-169-act-warning-repro-olm8o?expanddevtools=1&fontsize=14&hidenavigation=1&previewwindow=tests
act()
in first place runs all related useEffect
that would be async way otherwise. You don't see any difference since you don't have useEffect
in your component's code
According to Enzyme's docs in most recent version mount()
should be already wrapped with act()
internally:
If you're using React 16.8+ and
.mount()
, Enzyme will wrap apis including.simulate()
,.setProps()
,.setContext()
,.invoke()
withReactTestUtils.act()
so you don't need to manually wrap it.We cannot wrap the result of
.prop()
(or.props()
) with.act()
in Enzyme internally since it will break the equality of the returned value. However, you could use.invoke()
to simplify the code:
const wrapper = mount(<SomeComponent />);
wrapper.invoke('handler')();
expect(/* ... */);```