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();
});