简体   繁体   中英

When testing, code that causes React state updates should be wrapped into act(...) - with simple react-native nested screen/components with jest axios

I am new to unit testing/jest, but I know some about react native. I want to write a test for my HomeScreen, which contains a component that makes a simple request. The code runs without any issue but fails when I run it with Jest.

HomeScreen.js

import { View } from 'react-native'
import APIExample from '@components/Examples/APIExample'
const HomeScreen = () => {
    return (<View> <APIExample /> </View>)
}
export default HomeScreen

HomeScreen.test.js

import { render } from '@testing-library/react-native'
import HomeScreen from '@screens/HomeScreen'

it('should run', async () => {
    const { getByText } = await render(<HomeScreen />)
})

APIExample.js

import { useState, useEffect } from 'react'
import { Text, View } from 'react-native'
import API from '../../API'

const APIExample = () => {
    const [apiResponse, setApiResponse] = useState(null)

    const Submit = async () => {
        const response = await API.Test()
        setApiResponse(response)
    }
    useEffect(() => {
        Submit()
    }, [])
    return (
        <View>
            <Text>
                {JSON.stringify(apiResponse)}
            </Text>
        </View>
    )
}
export default APIExample

I try to figure out why does it keep saying that I should wrap it in act and what exactly do I need to wrap? I already tried to wrap the render whole line but had no success.

The API.Test is a simple axios.get

The error I've kept getting is:

Warning: An update to APIExample 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://reactjs.org/link/wrap-tests-with-act

It happened to me with fireEvent a couple of days ago. Try this:

await waitFor(()=> render(<HomeScreen />))

The reason you're facing the issue is because of state change that's happening. While on first render the apiResponse data is set as null. And later with the api response the apiResponse has a value so there is re-render that has occured, so jest complains about it.

To resolve you could use await waitFor(() => expect(api).toHaveBeenCalledTimes(1)) . This will wait for a specific period of time.

Suggestion: Mock your api's in tests, instead of hitting it directly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM