How to Mock useLocation Hook in React
Testing components that rely on the useLocation hook
from react-router-dom can be challenging because they
depend on the browser’s current URL. This article provides a
straightforward guide on how to mock the useLocation hook
using Jest and React Testing Library, covering both global module
mocking and dynamic route testing using wrapper components.
Method 1: Mocking react-router-dom Globally with Jest
The most direct way to mock useLocation is to use
jest.mock() at the top of your test file. This allows you
to define a fake implementation of the hook that returns a mock location
object.
import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';
// Mock the entire react-router-dom library
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useLocation: () => ({
pathname: '/dashboard',
search: '?user=test',
hash: '',
state: { from: 'login' }
}),
}));
test('renders component with mocked location data', () => {
render(<MyComponent />);
expect(screen.getByText(/dashboard/i)).toBeInTheDocument();
});Using jest.requireActual ensures that you only mock
useLocation while keeping other features of
react-router-dom intact.
Method 2: Mocking Dynamically for Individual Tests
If you need to test different paths or search parameters in different
test cases within the same file, you can mock the hook dynamically using
jest.spyOn.
import * as router from 'react-router-dom';
import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';
describe('MyComponent', () => {
const useLocationSpy = jest.spyOn(router, 'useLocation');
beforeEach(() => {
useLocationSpy.mockClear();
});
test('handles dashboard path', () => {
useLocationSpy.mockReturnValue({
pathname: '/dashboard',
search: '',
hash: '',
state: null,
});
render(<MyComponent />);
expect(screen.getByText('Welcome to Dashboard')).toBeInTheDocument();
});
test('handles settings path', () => {
useLocationSpy.mockReturnValue({
pathname: '/settings',
search: '',
hash: '',
state: null,
});
render(<MyComponent />);
expect(screen.getByText('Settings Page')).toBeInTheDocument();
});
});Method 3: Using MemoryRouter (Recommended Alternative)
Instead of manually mocking useLocation with Jest, the
official and recommended approach by the React Router team is to wrap
your component in a MemoryRouter. This allows you to set
the initial location naturally without stubbing library functions.
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import MyComponent from './MyComponent';
test('renders correctly on a specific route using MemoryRouter', () => {
render(
<MemoryRouter initialEntries={['/profile?id=123']}>
<MyComponent />
</MemoryRouter>
);
expect(screen.getByText(/User ID: 123/i)).toBeInTheDocument();
});Using MemoryRouter is generally preferred because it
tests your component in a way that closely mirrors how it runs in
production, reducing the risk of brittle tests that break during library
updates.