When testing components that use React Hooks, the goal is to ensure they behave correctly across renders, state changes, and side effects. You can use Jest and React Testing Library (RTL) to write effective tests.
For components that use useState, useEffect, or other Hooks, test their behavior, not implementation details.
useState in a Counter Componentimport { render, screen, fireEvent } from "@testing-library/react";
import Counter from "./Counter"; // Component using useState
test("increments counter on button click", () => {
render(<Counter />);
const button = screen.getByText("Count: 0");
fireEvent.click(button);
expect(screen.getByText("Count: 1")).toBeInTheDocument();
});
render().fireEvent.click().useEffect Side Effects (API Calls)For components that fetch data inside useEffect, mock API calls using Jest.
useEffectimport { render, screen, waitFor } from "@testing-library/react";
import axios from "axios";
import Users from "./Users"; // Fetches users from API
jest.mock("axios");
test("fetches and displays users", async () => {
axios.get.mockResolvedValue({ data: [{ name: "Alice" }] });
render(<Users />);
expect(screen.getByText(/Loading/i)).toBeInTheDocument();
// Wait for async data to load
await waitFor(() => screen.getByText("Alice"));
expect(screen.getByText("Alice")).toBeInTheDocument();
});
jest.mock().waitFor() to wait for async updates.For testing standalone Hooks, use the renderHook utility from @testing-library/react-hooks.
useCounter Hookimport { renderHook, act } from "@testing-library/react";
import { useCounter } from "./useCounter";
test("increments counter", () => {
const { result } = renderHook(() => useCounter());
act(() => result.current.increment());
expect(result.current.count).toBe(1);
});
renderHook() to call the Hook.act() to simulate state updates.| Hook Used | Testing Approach |
|---|---|
useState |
Simulate user events, check UI updates |
useEffect |
Mock API calls, use waitFor() |
useContext |
Wrap component in context provider |
useReducer |
Dispatch actions, verify state changes |
useCustomHook |
Use renderHook(), trigger updates with act() |