How to Mock useSearchParams in React

Testing React components that rely on URL parameters often requires mocking navigation hooks. This article provides a straightforward guide on how to mock the useSearchParams hook from popular libraries like React Router and Next.js using Jest. You will learn how to simulate query parameters in your test environment to ensure your components render and behave correctly.


Mocking useSearchParams in React Router

When using React Router, the useSearchParams hook returns an array containing the current URLSearchParams object and a function to update them.

You can mock this hook using jest.mock by returning a custom URLSearchParams instance.

import { render, screen } from '@testing-library/react';
import { useSearchParams } from 'react-router-dom';
import MyComponent from './MyComponent';

// Mock the react-router-dom library
jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  useSearchParams: () => [
    new URLSearchParams({ query: 'javascript', page: '2' }),
    jest.fn()
  ],
}));

test('should read query parameters correctly', () => {
  render(<MyComponent />);
  
  // Assertions based on mocked search params
  expect(screen.getByText('Search query: javascript')).toBeInTheDocument();
  expect(screen.getByText('Page: 2')).toBeInTheDocument();
});

Mocking useSearchParams in Next.js (App Router)

In Next.js (version 13 and above), the useSearchParams hook is imported from next/navigation and only returns the ReadonlyURLSearchParams object.

To mock this hook in a Next.js environment, mock the next/navigation module.

import { render, screen } from '@testing-library/react';
import SearchComponent from './SearchComponent';

// Mock the next/navigation library
jest.mock('next/navigation', () => ({
  useSearchParams: () => ({
    get: (key) => {
      const params = { term: 'nextjs' };
      return params[key] || null;
    },
    has: (key) => key === 'term',
  }),
}));

test('renders component with mock search term', () => {
  render(<SearchComponent />);
  
  expect(screen.getByText('Results for nextjs')).toBeInTheDocument();
});

Alternative: Mocking via Wrapper Components

For React Router, instead of manual mocking with jest.mock, you can wrap your component inside a MemoryRouter. This is often preferred because it tests real routing behavior.

Pass your query parameters directly into the initialEntries prop.

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

test('renders with URL parameters using MemoryRouter', () => {
  render(
    <MemoryRouter initialEntries={['/search?query=react&sort=desc']}>
      <Routes>
        <Route path="/search" element={<MyComponent />} />
      </Routes>
    </MemoryRouter>
  );

  expect(screen.getByText('Query: react')).toBeInTheDocument();
  expect(screen.getByText('Sort: desc')).toBeInTheDocument();
});