How to Test useParams Hook in React

Testing the useParams hook from React Router is essential for ensuring your components correctly read and respond to dynamic URL parameters. This guide provides a straightforward, step-by-step approach to testing components that utilize useParams using React Testing Library and Jest. You will learn the two most common and effective methods: wrapping your component in a MemoryRouter and mocking the react-router-dom library directly.


The Component Under Test

To demonstrate how to test useParams, we will use a simple component called UserProfile that retrieves an id from the URL and displays it.

import React from 'react';
import { useParams } from 'react-router-dom';

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

The most reliable way to test useParams is to wrap your component in a MemoryRouter from react-router-dom. This approach simulates actual routing behavior in your application without mocking external dependencies, making your tests more robust and closer to real-world usage.

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

test('renders user profile with ID from URL parameter', () => {
  render(
    <MemoryRouter initialEntries={['/users/123']}>
      <Routes>
        <Route path="/users/:id" element={<UserProfile />} />
      </Routes>
    </MemoryRouter>
  );

  // Assert that the component correctly reads "123" from the URL
  expect(screen.getByText('User Profile: 123')).toBeInTheDocument();
});

How it works:


Method 2: Mocking useParams with Jest

If you prefer to isolate your unit test and avoid rendering routing wrappers, you can mock the useParams hook directly using Jest. This method is faster but relies on internal implementation details of the routing library.

import React from 'react';
import { render, screen } from '@testing-library/react';
import { useParams } from 'react-router-dom';
import UserProfile from './UserProfile';

// Mock the entire react-router-dom library
jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  useParams: jest.fn(),
}));

test('renders user profile with mocked useParams value', () => {
  // Define the mock return value for this specific test
  useParams.mockReturnValue({ id: '456' });

  render(<UserProfile />);

  // Assert that the component correctly renders the mocked ID
  expect(screen.getByText('User Profile: 456')).toBeInTheDocument();
});

How it works: