How to Mock Context API in React
Testing React components that rely on the Context API requires a way to simulate context values without rendering your entire application tree. This article provides a straightforward guide on how to mock the React Context API in unit tests using Jest and React Testing Library. We will cover the two most effective methods: wrapping components with a Provider in your tests, and mocking the context hook directly with Jest.
Method 1: Wrapping Components with a Context Provider (Recommended)
The most reliable way to mock context is by wrapping the component under test with the actual Context Provider and passing a custom value. This closely mimics real-world behavior and avoids brittle implementation details.
1. The Component and Context
Assume you have a ThemeContext and a
ThemeButton component that consumes it:
// ThemeContext.js
import { createContext } from 'react';
export const ThemeContext = createContext('light');
// ThemeButton.js
import React, { useContext } from 'react';
import { ThemeContext } from './ThemeContext';
export function ThemeButton() {
const theme = useContext(ThemeContext);
return <button className={theme}>Active Theme: {theme}</button>;
}2. The Unit Test
In your test file, import the ThemeContext.Provider and
wrap the component inside the render function of React
Testing Library:
import React from 'react';
import { render, screen } from '@testing-library/react';
import { ThemeContext } from './ThemeContext';
import { ThemeButton } from './ThemeButton';
test('renders the component with custom context value', () => {
render(
<ThemeContext.Provider value="dark">
<ThemeButton />
</ThemeContext.Provider>
);
const button = screen.getByRole('button');
expect(button).toHaveTextContent('Active Theme: dark');
expect(button).toHaveClass('dark');
});Method 2: Mocking the Context Hook with Jest
If you want to isolate your component completely or avoid importing
the Provider, you can mock the useContext hook or a custom
context hook using jest.spyOn or
jest.mock.
1. The Custom Hook Component
Suppose you are using a custom hook to consume context:
// useUser.js
import { useContext } from 'react';
import { UserContext } from './UserContext';
export function useUser() {
return useContext(UserContext);
}
// UserProfile.js
import React from 'react';
import { useUser } from './useUser';
export function UserProfile() {
const { user } = useUser();
return <div>Welcome, {user.name}!</div>;
}2. Mocking the Hook in Jest
You can mock the return value of the custom hook before rendering the component:
import React from 'react';
import { render, screen } from '@testing-library/react';
import { UserProfile } from './UserProfile';
import * as UserHook from './useUser';
test('renders user profile with mocked custom hook', () => {
// Spy on the hook and mock its return value
const useUserSpy = jest.spyOn(UserHook, 'useUser');
useUserSpy.mockReturnValue({ user: { name: 'John Doe' } });
render(<UserProfile />);
expect(screen.getByText('Welcome, John Doe!')).toBeInTheDocument();
// Clean up the spy after the test
useUserSpy.mockRestore();
});Creating a Reusable Custom Render Function
If your application uses multiple contexts (e.g., Auth, Theme, Language), wrapping every test component manually can lead to boilerplate code. You can create a custom render function for your tests.
// test-utils.js
import React from 'react';
import { render } from '@testing-library/react';
import { ThemeContext } from './ThemeContext';
import { UserContext } from './UserContext';
const AllProviders = ({ children }) => {
return (
<UserContext.Provider value={{ user: { name: 'Test User' } }}>
<ThemeContext.Provider value="dark">
{children}
</ThemeContext.Provider>
</UserContext.Provider>
);
};
const customRender = (ui, options) =>
render(ui, { wrapper: AllProviders, ...options });
export * from '@testing-library/react';
export { customRender as render };Now, you can import this custom render function in your
test files instead of the default React Testing Library import,
automatically applying your mocked contexts to all test components.