How to Test MemoryRouter in React

Testing components that rely on routing in React can be challenging, but MemoryRouter from React Router simplifies this process by allowing you to simulate navigation in a test environment. This article provides a straightforward, step-by-step guide on how to configure and use MemoryRouter with React Testing Library to write reliable unit and integration tests for your routed components.

Why Use MemoryRouter for Testing?

When testing components that use React Router hooks (like useNavigate, useParams, or useLocation) or components like <Link>, wrapping them in a standard <BrowserRouter> will fail in a test environment. This is because Node.js environments (like Jest or Vitest) do not have a real browser history stack.

MemoryRouter solves this by storing the navigation history in memory. It allows you to: * Simulate specific URLs and paths. * Test components that depend on URL parameters. * Assert that navigation occurs correctly without needing a real browser.


Step-by-Step Implementation

1. Create the Component to Test

Consider a simple UserProfile component that reads a user ID from the URL parameters using useParams:

// UserProfile.jsx
import React from 'react';
import { useParams } from 'react-router-dom';

export function UserProfile() {
  const { id } = useParams();
  return (
    <div>
      <h1>User Profile</h1>
      <p>Current User ID: {id}</p>
    </div>
  );
}

2. Write the Test Using MemoryRouter

To test this component, you must wrap it in a <MemoryRouter> inside your test file. You can use the initialEntries prop to define the starting URL path.

// UserProfile.test.jsx
import React from 'react';
import { render, screen } from '@testing-library/react';
import { MemoryRouter, Routes, Route } from 'react-router-dom';
import { UserProfile } from './UserProfile';

describe('UserProfile Component', () => {
  it('renders the correct user ID from the URL path', () => {
    render(
      <MemoryRouter initialEntries={['/user/99']}>
        <Routes>
          <Route path="/user/:id" element={<UserProfile />} />
        </Routes>
      </MemoryRouter>
    );

    // Assert that the component correctly reads "99" from the simulated URL
    expect(screen.getByText('Current User ID: 99')).toBeInTheDocument();
  });
});

Key Props of MemoryRouter to Know

When configuring your tests, you will primarily use two props on <MemoryRouter>:


Best Practices for Testing Routing

  1. Keep Tests Isolated: Use a fresh <MemoryRouter> instance for each test case to prevent state or history leakage between tests.
  2. Mimic Real Route Configurations: If the component under test depends on parent or sibling routes, replicate that structure inside your test using <Routes> and <Route> wrappers as shown in the example above.
  3. Avoid Testing the Router Itself: Focus on testing your application’s behavior (e.g., “does the correct UI load when the URL is X?”) rather than verifying if React Router’s internal code functions correctly.