How to Mock React Router in Jest
Testing components that rely on React Router requires simulating
routing behavior without running a full browser environment. This
article provides a straightforward guide on how to mock React Router in
your Jest tests, covering both the integration testing approach using
MemoryRouter and the unit testing approach using Jest
module mocks to spy on hooks like useNavigate and
useParams.
Approach 1: Using MemoryRouter (Recommended)
The most robust way to test components that use React Router is to
wrap them in the MemoryRouter component provided by
react-router-dom. This avoids actual mocking and instead
provides a real, in-memory routing context to your components.
This approach is ideal when your component contains links or route-matching logic.
import { render, screen } from '@testing-library/react';
import { MemoryRouter, Routes, Route } from 'react-router-dom';
import UserProfile from './UserProfile';
test('renders user profile based on route parameter', () => {
render(
<MemoryRouter initialEntries={['/user/42']}>
<Routes>
<Route path="/user/:id" element={<UserProfile />} />
</Routes>
</MemoryRouter>
);
expect(screen.getByText(/User ID: 42/i)).toBeInTheDocument();
});Approach 2: Mocking Hooks with jest.mock()
If you only need to assert that a routing hook was called (for
example, verifying that a button click redirects the user), you can mock
the react-router-dom library directly using Jest.
Mocking useNavigate
To assert that useNavigate was called with the correct
path, mock the hook at the top of your test file.
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { useNavigate } from 'react-router-dom';
import MyButton from './MyButton';
// Create a mock navigation function
const mockNavigate = jest.fn();
// Mock the react-router-dom module
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useNavigate: () => mockNavigate,
}));
test('navigates to dashboard on button click', async () => {
render(<MyButton />);
const button = screen.getByRole('button', { name: /go to dashboard/i });
await userEvent.click(button);
expect(mockNavigate).toHaveBeenCalledWith('/dashboard');
});Mocking useParams
If you want to mock URL path parameters without setting up a full
router structure in your tests, you can mock useParams to
return a specific object.
import { render, screen } from '@testing-library/react';
import ProductDetails from './ProductDetails';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: () => ({ productId: 'abc-123' }),
}));
test('displays the product ID from URL params', () => {
render(<ProductDetails />);
expect(screen.getByText(/Product: abc-123/i)).toBeInTheDocument();
});