How to Mock Router Routes in React
Testing components that rely on React Router requires simulating the
routing environment without running a full browser instance. This
article provides a straightforward guide on how to mock router routes in
React using React Router’s built-in MemoryRouter for
integration tests, as well as how to mock specific routing hooks like
useNavigate and useParams using Jest.
Method 1: Using MemoryRouter (Recommended)
The most effective way to mock routes in React Router (v6+) is by
wrapping your component in a MemoryRouter. This component
stores its locations internally in an array, making it ideal for testing
environments like Jest and React Testing Library.
You can define the current path using the initialEntries
prop.
import { render, screen } from '@testing-library/react';
import { MemoryRouter, Routes, Route } from 'react-router-dom';
import UserProfile from './UserProfile';
test('renders UserProfile with correct ID from URL', () => {
render(
<MemoryRouter initialEntries={['/users/42']}>
<Routes>
<Route path="/users/:id" element={<UserProfile />} />
</Routes>
</MemoryRouter>
);
expect(screen.getByText(/User ID: 42/i)).toBeInTheDocument();
});Method 2: Mocking React Router Hooks
Sometimes you want to assert that a navigation action has occurred (e.g., clicking a button redirects the user). In this case, you should mock the hooks directly.
Mocking useNavigate
To verify if useNavigate is called with the correct
path, mock the react-router-dom library using Jest.
import { render, screen, fireEvent } from '@testing-library/react';
import MyForm from './MyForm';
const mockNavigate = jest.fn();
// Mock the react-router-dom module
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useNavigate: () => mockNavigate,
}));
test('redirects to dashboard on form submission', () => {
render(<MyForm />);
const submitButton = screen.getByRole('button', { name: /submit/i });
fireEvent.click(submitButton);
expect(mockNavigate).toHaveBeenCalledWith('/dashboard');
});Mocking useParams
If you are writing a unit test for a component and do not want to set
up a MemoryRouter wrapper, you can mock
useParams directly.
import { render, screen } from '@testing-library/react';
import ProductDetail from './ProductDetail';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: () => ({ productId: 'abc-987' }),
}));
test('displays the correct product ID', () => {
render(<ProductDetail />);
expect(screen.getByText(/Product: abc-987/i)).toBeInTheDocument();
});