How to Mock useContext Hook in React
Testing React components that rely on the useContext
hook is a common requirement in modern frontend development. This
article provides a straightforward guide on how to mock the
useContext hook in React using Jest and React Testing
Library. We will explore the two primary methods for accomplishing this:
wrapping the component with a real Context Provider, and directly
mocking the React.useContext function.
Method 1: Wrapping with a Context Provider (Recommended)
The most reliable and idiomatic way to mock context is by wrapping
your component with the context’s actual Provider during
the test. This closely mimics how the component runs in production and
avoids modifying React’s internal APIs.
Consider the following component that consumes a
UserContext:
// UserProfile.js
import React, { createContext, useContext } from 'react';
export const UserContext = createContext(null);
export const UserProfile = () => {
const user = useContext(UserContext);
return (
<div>
{user ? <h1>Welcome, {user.name}!</h1> : <h1>Please log in.</h1>}
</div>
);
};To test this component, wrap it with
UserContext.Provider in your test file and pass a mock
value to the value prop:
// UserProfile.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import { UserContext, UserProfile } from './UserProfile';
test('renders welcome message for logged in user', () => {
const mockUser = { name: 'John Doe' };
render(
<UserContext.Provider value={mockUser}>
<UserProfile />
</UserContext.Provider>
);
expect(screen.getByText('Welcome, John Doe!')).toBeInTheDocument();
});
test('renders login prompt when no user is provided', () => {
render(
<UserContext.Provider value={null}>
<UserProfile />
</UserContext.Provider>
);
expect(screen.getByText('Please log in.')).toBeInTheDocument();
});Method 2: Mocking React.useContext Directly
If you want to isolate your component completely and avoid importing
the context provider into your test files, you can mock the
useContext hook directly using jest.spyOn.
This approach is useful when dealing with deeply nested contexts or when the context provider is difficult to instantiate in a test environment.
// UserProfile.spy.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import { UserProfile } from './UserProfile';
describe('UserProfile - Spy Mocking', () => {
afterEach(() => {
jest.restoreAllMocks();
});
test('renders welcome message using spyOn', () => {
const mockUser = { name: 'Jane Doe' };
// Spy on React.useContext and return the mock user
jest.spyOn(React, 'useContext').mockReturnValue(mockUser);
render(<UserProfile />);
expect(screen.getByText('Welcome, Jane Doe!')).toBeInTheDocument();
});
});Note: When using jest.spyOn on React hooks, ensure
you restore the mocks after each test to prevent side effects from
leaking into other test suites.