Clean β’ Professional
In React applications, components often depend on APIs or external modules. During testing, you donβt want to make real network requests or rely on actual modules. This is where mocking comes in handy. Mocking allows you to simulate external dependencies and test your components in isolation.
Suppose you have a component that fetches user data:
// UserProfile.jsx
import React, { useEffect, useState } from "react";
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/users/${userId}`)
.then(res => res.json())
.then(data => setUser(data));
}, [userId]);
if (!user) return <p>Loading...</p>;
return <div>{user.name}</div>;
}
export default UserProfile;
// UserProfile.test.jsx
import React from "react";
import { render, screen, waitFor } from "@testing-library/react";
import UserProfile from "./UserProfile";
// Mock the global fetch function
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ name: "John Doe" }),
})
);
test("renders user name after API call", async () => {
render(<UserProfile userId={1} />);
// Wait for the user name to appear
const userName = await waitFor(() => screen.getByText("John Doe"));
expect(userName).toBeInTheDocument();
expect(fetch).toHaveBeenCalledTimes(1);
expect(fetch).toHaveBeenCalledWith(
"<https://jsonplaceholder.typicode.com/users/1>"
);
});
jest.fn() β creates a mock functionPromise.resolve() β simulates async API responsewaitFor() β waits for async updates in the componentSometimes, you want to mock entire modules, such as utility functions.
// utils.js
export const calculateDiscount = (price) => price * 0.9;
// Component.jsx
import React from "react";
import { calculateDiscount } from "./utils";
function Price({ amount }) {
return <p>Discounted Price: {calculateDiscount(amount)}</p>;
}
export default Price;
// Component.test.jsx
import React from "react";
import { render, screen } from "@testing-library/react";
import Price from "./Component";
// Mock the module
jest.mock("./utils", () => ({
calculateDiscount: jest.fn(() => 50), // always return 50
}));
test("renders mocked discounted price", () => {
render(<Price amount={100} />);
expect(screen.getByText("Discounted Price: 50")).toBeInTheDocument();
});
Benefits:
When a parent passes functions to a child, you can mock them with Jest to verify interactions.
function Button({ onClick }) {
return <button onClick={onClick}>Click Me</button>;
}
// Test
test("calls onClick handler when clicked", () => {
const handleClick = jest.fn();
render(<Button onClick={handleClick} />);
screen.getByText("Click Me").click();
expect(handleClick).toHaveBeenCalledTimes(1);
});
jest.fn() creates a spy functiontoHaveBeenCalledTimes ensures the function was triggered