How to Mock StaticRouter in React
Testing React components that rely on routing requires setting up a
mock routing environment so hooks like useLocation or
useNavigate do not throw errors. This article explains how
to mock StaticRouter in your unit tests, covering both how
to use it as a test wrapper and how to mock the module export itself
using Jest and React Testing Library.
Option 1: Using StaticRouter to Mock the Routing Context
If you want to test a component that consumes routing context (like
links or route parameters), you can wrap it in StaticRouter
within your test. This provides a fixed, non-interactive routing
context.
Note that in React Router v6, StaticRouter is imported
from react-router-dom/server.
import React from 'react';
import { render, screen } from '@testing-library/react';
import { StaticRouter } from 'react-router-dom/server';
import SidebarNavigation from './SidebarNavigation';
describe('SidebarNavigation Component', () => {
it('renders navigation links with the correct active state', () => {
render(
<StaticRouter location="/dashboard">
<SidebarNavigation />
</StaticRouter>
);
const dashboardLink = screen.getByRole('link', { name: /dashboard/i });
expect(dashboardLink).toBeInTheDocument();
});
});Using StaticRouter is ideal for testing static
server-rendered outputs or when you only need to assert that a component
renders correctly at a specific URL.
Option 2: Mocking the StaticRouter Module Export
If the component you are testing imports StaticRouter
directly (for example, in a Server-Side Rendering entry point) and you
want to mock the component itself to avoid running its actual code
during tests, you can use jest.mock.
Here is how to mock the StaticRouter export from
react-router-dom/server:
import React from 'react';
import { render, screen } from '@testing-library/react';
import AppServerEntry from './AppServerEntry';
// Mock the StaticRouter from react-router-dom/server
jest.mock('react-router-dom/server', () => ({
StaticRouter: ({ children, location }) => (
<div data-testid="mock-static-router" data-location={location}>
{children}
</div>
),
}));
describe('AppServerEntry Component', () => {
it('wraps the application in the mocked StaticRouter', () => {
render(<AppServerEntry url="/profile" />);
const mockRouter = screen.getByTestId('mock-static-router');
expect(mockRouter).toBeInTheDocument();
expect(mockRouter).toHaveAttribute('data-location', '/profile');
});
});Option 3: Replacing StaticRouter with MemoryRouter in Tests
For most client-side interaction and navigation tests, using
MemoryRouter from react-router-dom is
preferred over StaticRouter. MemoryRouter
keeps the history of your routing in memory, allowing you to test
dynamic redirects and navigation actions.
import React from 'react';
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import ProfileCard from './ProfileCard';
test('renders profile page using MemoryRouter', () => {
render(
<MemoryRouter initialEntries={['/user/123']}>
<ProfileCard />
</MemoryRouter>
);
expect(screen.getByText(/User ID: 123/i)).toBeInTheDocument();
});