Testing React's useEffect Hook with Jest
Testing asynchronous behavior in React components, particularly those involving side effects managed by useEffect, can be tricky. This challenge will guide you through writing effective Jest tests for a component that utilizes useEffect to fetch data on mount and to update its state based on that data. Mastering this will improve your ability to test real-world React applications.
Problem Description
You need to write Jest tests for a simple React functional component called UserProfile. This component, when rendered, should fetch user data from a mock API endpoint. After the data is fetched, it should display the user's name and email.
Your primary goal is to test the behavior triggered by the useEffect hook:
- Data Fetching on Mount: Ensure that
useEffectcorrectly initiates a data fetch operation when the component mounts. - State Update: Verify that the component's state is updated with the fetched user data, and that this data is rendered correctly.
- Error Handling (Optional but Recommended): If the data fetching fails, the component should display an error message.
You will be provided with a mock fetch function and a basic UserProfile component. Your task is to write the Jest test suite using @testing-library/react and Jest.
Key Requirements:
- Use
jest.fn()to mock thefetchAPI. - Test that
fetchis called with the correct URL. - Test that the component renders the user's name and email after successful data fetching.
- Test that an error message is rendered when the
fetchpromise rejects. - Ensure your tests are asynchronous and handle the completion of
useEffect.
Expected Behavior:
- Initially, the component might show a loading indicator (or nothing specific, depending on implementation).
- Upon successful fetch, the component displays the user's name and email.
- Upon failed fetch, the component displays an error message.
Edge Cases to Consider:
- What happens if the
fetchresponse is not OK (e.g., 404, 500)? - How do you ensure your tests wait for asynchronous operations like
fetchto complete?
Examples
Let's assume the following mock fetch and a simplified UserProfile component structure for illustrative purposes. You will be given the actual code to test.
Mock fetch Response (Success):
{
"name": "Jane Doe",
"email": "jane.doe@example.com"
}
Mock fetch Response (Error):
An error object or a response with ok: false.
Example 1: Successful Data Fetch
- Scenario: The
fetchcall successfully resolves with user data. - Expected Rendered Output:
User Name: Jane Doe User Email: jane.doe@example.com - Explanation: The
useEffecthook triggersfetch. The promise resolves, the data is processed, the component's state is updated, and the new data is displayed.
Example 2: Failed Data Fetch
- Scenario: The
fetchcall rejects or returns an error status. - Expected Rendered Output:
Error fetching user data. - Explanation: The
useEffecthook triggersfetch. The promise rejects or the response indicates an error. The error handling logic within theuseEffectis executed, and an error message is displayed.
Constraints
- You must use TypeScript for your test files.
- The tests should be written using Jest and
@testing-library/react. - The mock
fetchfunction will be provided. - Assume network requests are simulated and will complete within a reasonable time frame for testing.
Notes
- Remember to use
waitFororscreen.findBy*methods from@testing-library/reactto handle asynchronous updates. - Consider how you will mock the global
fetchAPI for your tests. Thejest.spyOnorjest.mockfunctions will be useful here. - Think about the initial state of the component before
useEffecthas completed its work. - The provided component might have a loading state; ensure your tests account for this if present.