Mocking in Jest for Next.js: A Comprehensive Guide
Author
Abhishek Chaubey
Date Published

When writing unit tests for a Next.js application, isolating dependencies is crucial for ensuring that tests remain focused and fast. Mocking in Jest provides a way to replace real implementations of modules, functions, or objects with controlled versions, allowing you to test specific behaviors without relying on external dependencies. In this article, we'll dive deep into various mocking techniques with practical examples tailored for Next.js applications.
Mocking API Calls with Axios
In many Next.js projects, you’ll interact with external APIs, and using Axios is a common choice for making HTTP requests. However, during tests, you don't want to make real API calls, so mocking Axios allows you to simulate network requests and focus on testing your logic.
Example: Mocking Axios for GET Requests
Let’s assume you have a function that fetches data from an API:
1// lib/api.ts2import axios from 'axios';34export const fetchData = async () => {5 const response = await axios.get('/api/data');6 return response.data;7};
In your tests, you can mock Axios to return a predefined response:
1// tests/lib/api.test.ts2import axios from 'axios';3import { fetchData } from '@/lib/api';45jest.mock('axios'); // Mock Axios globally6const mockedAxios = axios as jest.Mocked<typeof axios>;78describe('fetchData', () => {9 it('should fetch and return data', async () => {10 const mockResponse = { data: { message: 'Hello, world!' } };11 mockedAxios.get.mockResolvedValue(mockResponse); // Mock the GET request1213 const data = await fetchData();14 expect(data).toEqual({ message: 'Hello, world!' });15 expect(mockedAxios.get).toHaveBeenCalledWith('/api/data');16 });17});
Explanation:
jest.mock('axios'): This tells Jest to mock the axios module.
mockResolvedValue: This simulates a successful API response with the given mockResponse.
toHaveBeenCalledWith: This checks if the Axios get method was called with the correct URL.
Mocking Next.js Router
The Next.js useRouter hook is commonly used for navigation and retrieving route-specific data. When writing tests for components that rely on routing, it’s important to mock this hook to avoid running tests in a real routing environment.
Example: Mocking useRouter for Navigation
1import { useRouter } from 'next/router';23const MyComponent = () => {4 const router = useRouter();5 return <div>{router.route}</div>;6};78export default MyComponent;
To mock useRouter in a test:
1// tests/components/MyComponent.test.tsx2import { render, screen } from '@testing-library/react';3import { useRouter } from 'next/router';4import MyComponent from '@/components/MyComponent';56// Mock the useRouter hook7jest.mock('next/router', () => ({8 useRouter: jest.fn(),9}));1011describe('MyComponent', () => {12 it('renders the current route', () => {13 // Mock the useRouter hook's return value14 (useRouter as jest.Mock).mockReturnValue({ route: '/home' });1516 render(<MyComponent />);17 const routeElement = screen.getByText('/home');18 expect(routeElement).toBeInTheDocument();19 });20});21
Explanation:
jest.mock('next/router'): This tells Jest to mock the Next.js useRouter hook.
(useRouter as jest.Mock).mockReturnValue: This sets a mocked return value for the useRouter hook, so we can simulate a route.
getByText: This is used to check if the current route is rendered correctly.
Mocking Date and Time
In some cases, you may need to mock the current date or time, especially when testing components that depend on time-sensitive data (e.g., a countdown timer or an event).
Example: Mocking Date for Testing Time-Based Logic
1// components/DateDisplay.tsx2const DateDisplay = () => {3 const currentDate = new Date().toLocaleDateString();4 return <div>{currentDate}</div>;5};67export default DateDisplay;
In your tests, you can mock the Date object to control the current date:
1// tests/components/DateDisplay.test.tsx2import { render, screen } from '@testing-library/react';3import DateDisplay from '@/components/DateDisplay';45// Mock the Date object6const mockDate = new Date(2024, 11, 25); // December 25, 20247global.Date = jest.fn(() => mockDate); // Override Date globally89describe('DateDisplay', () => {10 it('displays the mocked current date', () => {11 render(<DateDisplay />);12 const dateElement = screen.getByText('12/25/2024');13 expect(dateElement).toBeInTheDocument();14 });15});
Explanation:
global.Date = jest.fn(() => mockDate): This mocks the global Date object to always return the mocked date during tests.
The test then ensures that the rendered date matches the mocked date.
Mocking Browser-Specific APIs (e.g., window or localStorage)
In a Next.js project, you may encounter browser-specific APIs such as window or localStorage, which are not available in a Node.js environment. When writing tests that interact with these APIs, you can mock them to simulate their behavior.
Example: Mocking localStorage
1// components/LocalStorageComponent.tsx2const LocalStorageComponent = () => {3 const saveData = () => {4 localStorage.setItem('username', 'JohnDoe');5 };67 return <button onClick={saveData}>Save Data</button>;8};910export default LocalStorageComponent;
In your test, you can mock localStorage like this:
1// tests/components/LocalStorageComponent.test.tsx2import { render, screen, fireEvent } from '@testing-library/react';3import LocalStorageComponent from '@/components/LocalStorageComponent';45// Mock localStorage6beforeAll(() => {7 const localStorageMock = {8 getItem: jest.fn(),9 setItem: jest.fn(),10 removeItem: jest.fn(),11 clear: jest.fn(),12 };13 global.localStorage = localStorageMock; // Override localStorage globally14});1516describe('LocalStorageComponent', () => {17 it('saves data to localStorage when the button is clicked', () => {18 render(<LocalStorageComponent />);19 const button = screen.getByText('Save Data');20 fireEvent.click(button);21 expect(localStorage.setItem).toHaveBeenCalledWith('username', 'JohnDoe');22 });23});
Explanation
beforeAll: Sets up the mock for localStorage before any tests run.
global.localStorage = localStorageMock: Replaces the global localStorage with the mock object.
fireEvent.click(button): Simulates a button click that triggers the localStorage.setItem method.
Conclusion
Mocking is an essential technique when writing unit tests in Jest for Next.js projects. It allows you to isolate dependencies, simulate behavior, and test components in isolation. Whether you’re working with APIs, browser-specific features, or routing, Jest provides powerful tools to mock various aspects of your application, making your tests faster and more reliable.
By using the techniques and examples outlined in this article, you can handle complex testing scenarios with ease. Mocking helps ensure that your components behave as expected without relying on external services or resources, making it a crucial part of the testing process.

When working with Next.js, testing is an essential part of the development process to ensure your app functions as expected.