How to Test React Router Routes
Testing routing in React ensures that your application navigates
correctly and renders the appropriate components when URLs change. This
article provides a straightforward guide on how to test React Router
routes using React Testing Library and Jest or Vitest. You will learn
how to set up testing environments using MemoryRouter, mock
navigation, and assert that the correct pages load based on user
interaction or initial URL states.
Why Use MemoryRouter for Testing?
When testing React applications that use React Router, you cannot
easily use the standard BrowserRouter because it relies on
the browser’s history API, which is not available in a Node.js testing
environment (like Jest or Vitest).
Instead, React Router provides
MemoryRouter. This router stores its
locations internally in an array, making it ideal for testing routing
behavior without a real browser window.
Testing Static Routes
To test if a specific route renders the correct component, wrap the
component under test in a MemoryRouter and use the
initialEntries prop to set the starting URL path.
The Component under Test
// App.jsx
import { Routes, Route, Link } from 'react-router-dom';
export const Home = () => <div>Home Page</div>;
export const About = () => <div>About Page</div>;
export const NotFound = () => <div>Page Not Found</div>;
export const App = () => (
<div>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="*" element={<NotFound />} />
</Routes>
</div>
);The Test File
// App.test.jsx
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { App } from './App';
describe('App Routing', () => {
test('renders Home Page on default route', () => {
render(
<MemoryRouter initialEntries={['/']}>
<App />
</MemoryRouter>
);
expect(screen.getByText(/Home Page/i)).toBeInTheDocument();
});
test('renders About Page when URL is /about', () => {
render(
<MemoryRouter initialEntries={['/about']}>
<App />
</MemoryRouter>
);
expect(screen.getByText(/About Page/i)).toBeInTheDocument();
});
test('renders Page Not Found on a bad route', () => {
render(
<MemoryRouter initialEntries={['/this-route-does-not-exist']}>
<App />
</MemoryRouter>
);
expect(screen.getByText(/Page Not Found/i)).toBeInTheDocument();
});
});Testing User Navigation
To test that clicking a link successfully navigates the user to a new
route, use user-event to simulate a mouse click and assert
that the new component appears in the DOM.
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MemoryRouter } from 'react-router-dom';
import { App } from './App';
test('navigates to About Page when the link is clicked', async () => {
render(
<MemoryRouter initialEntries={['/']}>
<App />
</MemoryRouter>
);
// Verify we start on the home page
expect(screen.getByText(/Home Page/i)).toBeInTheDocument();
// Click the About link
const aboutLink = screen.getByRole('link', { name: /about/i });
await userEvent.click(aboutLink);
// Verify the URL change rendered the About component
expect(screen.getByText(/About Page/i)).toBeInTheDocument();
});Best Practices for Routing Tests
- Keep components isolated: If you only want to test
a single page’s behavior, wrap just that page component in
MemoryRouter. - Use
initialEntries: Always explicitly define the initial route entry so your tests are predictable and do not rely on implicit defaults. - Avoid mocking the router: Whenever possible, test
the actual router integration rather than mocking
react-router-domfunctions. This guarantees that your configuration works in production.