Design Converter
Education
Last updated on Feb 18, 2025
•5 mins read
Last updated on Feb 18, 2025
•5 mins read
Software Development Executive - I
Builds things that work. And if it doesn’t, he’ll fix it — with Neovim, of course.
Testing your React applications ensures they behave as expected and are resilient to changes. When it comes to testing navigation and routing, React Router enables seamless client-side navigation in React applications, ensuring that users can move between different views without full-page reloads.
In this article, we’ll cover key concepts, practical examples, and step-by-step approaches for testing React Router. By the end, you’ll understand how to efficiently test router components, validate route paths, and mock navigation flows using React Testing Library.
React Router is an essential tool for client-side navigation in modern React applications. Whether you’re handling route components or nested routes, it’s critical to ensure every page and navigation interaction behaves as expected.
Verifying that the correct component renders for a given route path.
Mocking navigation using the MemoryRouter component.
Checking router history and validating the history stack.
Testing dynamic routing behavior and navigation using the useNavigate hook.
Before we start writing tests, you need to ensure your React Testing Library setup is complete. Here’s a quick setup guide.
1npm install --save-dev @testing-library/react @testing-library/jest-dom react-router-dom
Install the necessary packages for testing with the following command:
• @testing-library/react
: For testing React components
• @testing-library/jest-dom
: Provides custom matchers for assertions
• react-router-dom
: Implements React Router."
Assume a simple React Router app with these routes:
• /
- Home Page
• /about
- About Page
• /dashboard
- Dashboard Page (protected route)
In the following example, we create a simple app with three routes (Home, About, and Dashboard) using React Router
1// App.js 2import React from 'react'; 3import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom'; 4import Home from './Home'; 5import About from './About'; 6import Dashboard from './Dashboard'; 7 8const App = () => ( 9 <Router> 10 <nav> 11 <Link to="/">Home</Link> 12 <Link to="/about">About</Link> 13 <Link to="/dashboard">Dashboard</Link> 14 </nav> 15 <Routes> 16 <Route path="/" element={<Home />} /> 17 <Route path="/about" element={<About />} /> 18 <Route path="/dashboard" element={<Dashboard />} /> 19 </Routes> 20 </Router> 21); 22 23export default App;
When writing unit tests for React Router, we simulate navigation using React Testing Library and verify the correct component is rendered.
The memoryRouter component is ideal for tests because it keeps navigation in memory rather than relying on a physical window object.
1import { render, screen } from '@testing-library/react'; 2import { MemoryRouter } from 'react-router-dom'; 3import App from './App'; 4 5test('renders the home page by default', () => { 6 render( 7 <MemoryRouter initialEntries={['/']}> 8 <App /> 9 </MemoryRouter> 10 ); 11 expect(screen.getByText('Welcome to the Home Page')).toBeInTheDocument(); 12}); 13 14test('navigates to the about page', async () => { 15 render( 16 <MemoryRouter initialEntries={['/about']}> 17 <App /> 18 </MemoryRouter> 19 ); 20 expect(screen.getByText('About Us')).toBeInTheDocument(); 21});
In these tests, we pass the initialEntries prop to MemoryRouter to simulate different route paths.
The useNavigate hook helps programmatic navigation in React Router, which can be tested by mocking the hook.
1import { render, fireEvent } from '@testing-library/react'; 2import { useNavigate } from 'react-router-dom'; 3import MyComponent from './MyComponent'; 4 5jest.mock('react-router-dom', () => ({ 6 ...jest.requireActual('react-router-dom'), 7 useNavigate: jest.fn(), 8})); 9 10test('navigates to a specific route on button click', () => { 11 const navigate = jest.fn(); 12 useNavigate.mockReturnValue(navigate); 13 14 render(<MyComponent />); 15 16 fireEvent.click(screen.getByText('Go to Dashboard')); 17 expect(navigate).toHaveBeenCalledWith('/dashboard'); 18});
In this example, we mock the useNavigate hook to test that navigation to a specific route occurs correctly.
Sometimes, you want to ensure that a route component renders based on the current URL path.
1import { render, screen } from '@testing-library/react'; 2import { MemoryRouter, Route, Routes } from 'react-router-dom'; 3import ProtectedRoute from './ProtectedRoute'; 4import Dashboard from './Dashboard'; 5 6// ProtectedRoute handles redirection if the user is not authenticated. 7 8test('redirects to login if user is not authenticated', () => { 9 render( 10 <MemoryRouter initialEntries={['/dashboard']}> 11 <Routes> 12 <Route path="/dashboard" element={<ProtectedRoute><Dashboard /></ProtectedRoute>} /> 13 <Route path="/login" element={<div>Login Page</div>} /> 14 </Routes> 15 </MemoryRouter> 16 ); 17 18 expect(screen.getByText('Login Page')).toBeInTheDocument(); 19});
In this test, we simulate an unauthenticated user being redirected to the login page when attempting to access a protected route.
When React Testing Library tests interact with APIs, mocking responses is essential to avoid relying on actual network calls.
1import { render, screen, waitFor } from '@testing-library/react'; 2import axios from 'axios'; 3import UserProfile from './UserProfile'; 4 5jest.mock('axios'); 6 7test('displays user data after fetching', async () => { 8 axios.get.mockResolvedValue({ data: { name: 'John Doe' } }); 9 10 render(<UserProfile />); 11 12 await waitFor(() => expect(screen.getByText('John Doe')).toBeInTheDocument()); 13});
Here, we mock the axios library to simulate an API response without making a real request.
Use MemoryRouter for isolated tests: This ensures routing logic is kept in memory and doesn’t depend on browser APIs.
Mock the useNavigate hook for testing programmatic navigation.
Test components individually and verify their behavior within specific routes.
Simulate different route paths with initialEntries in MemoryRouter.
Always test edge cases, such as invalid paths and redirects.
Testing React Router with React Testing Library is vital for creating reliable and maintainable React applications. By understanding how to test navigation, mock hooks like useNavigate, and validate router components, you can write comprehensive unit tests. Always focus on testing route components, router history, and path-based rendering to ensure your app's routing works seamlessly.
By mastering these techniques, you’ll be well-equipped to test even the most complex React Router implementations.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.