Jest Mock Patterns
jest.fn() โ Mock Functions
// Create a mock function
const mockFn = jest.fn();
mockFn('hello');
expect(mockFn).toHaveBeenCalledWith('hello');
expect(mockFn).toHaveBeenCalledTimes(1);
// Set return values
const add = jest.fn().mockReturnValue(42);
const addAsync = jest.fn().mockResolvedValue({ id: 1, name: 'Alice' });
const addOnce = jest.fn()
.mockReturnValueOnce(1)
.mockReturnValueOnce(2)
.mockReturnValue(0); // default fallback
// Mock implementation
const greet = jest.fn((name) => `Hello, ${name}!`);
expect(greet('World')).toBe('Hello, World!');
// Inspect calls
console.log(mockFn.mock.calls); // [[arg1, arg2], ...]
console.log(mockFn.mock.results); // [{ type: 'return', value: ... }]
console.log(mockFn.mock.instances); // `this` for each call
// Reset / restore
mockFn.mockClear(); // clears calls/results
mockFn.mockReset(); // also removes implementation
mockFn.mockRestore(); // only works with spyOn
jest.mock() โ Module Mocking
// Auto-mock an entire module
jest.mock('./utils/api');
import { fetchUser } from './utils/api';
// fetchUser is now jest.fn()
// Partial mock โ keep some real implementations
jest.mock('./utils/helpers', () => ({
...jest.requireActual('./utils/helpers'),
formatDate: jest.fn(() => '2024-01-01'),
}));
// Mock with factory (runs before imports)
jest.mock('axios', () => ({
default: {
get: jest.fn(),
post: jest.fn(),
},
}));
// Inside tests
import axios from 'axios';
(axios.get as jest.Mock).mockResolvedValue({ data: { id: 1 } });
const result = await fetchData('/users/1');
expect(axios.get).toHaveBeenCalledWith('/users/1');
// Reset all mocks between tests
afterEach(() => {
jest.clearAllMocks();
});
jest.spyOn() โ Spy on Real Methods
import * as mathUtils from './mathUtils';
// Spy without changing implementation
const spy = jest.spyOn(mathUtils, 'add');
mathUtils.add(2, 3);
expect(spy).toHaveBeenCalledWith(2, 3);
// Override implementation temporarily
jest.spyOn(console, 'error').mockImplementation(() => {});
// Spy on class methods
class UserService {
async getUser(id: string) { /* ... */ }
}
const service = new UserService();
const getSpy = jest.spyOn(service, 'getUser').mockResolvedValue({ id: '1', name: 'Alice' });
await service.getUser('1');
expect(getSpy).toHaveBeenCalledWith('1');
// Always restore spies
afterEach(() => {
jest.restoreAllMocks();
});
Manual Mocks โ __mocks__ Directory
// __mocks__/fs.js โ manual mock for Node built-in
'use strict';
const path = require('path');
const MOCK_FILE_INFO = {};
const fs = jest.createMockFromModule('fs');
fs.readFileSync = jest.fn((filePath) => {
if (MOCK_FILE_INFO[filePath]) return MOCK_FILE_INFO[filePath];
throw new Error(`File not found: ${filePath}`);
});
fs.__setMockFiles = (newMockFiles) => {
Object.assign(MOCK_FILE_INFO, newMockFiles);
};
module.exports = fs;
// In your test:
jest.mock('fs');
const fs = require('fs');
fs.__setMockFiles({ '/etc/config.json': '{"key":"val"}' });
// For local modules: place __mocks__ next to module
// src/utils/__mocks__/database.ts
export const query = jest.fn().mockResolvedValue([]);
export const close = jest.fn();
Timer Mocks โ Fake Timers
// Enable fake timers
jest.useFakeTimers();
test('debounce fires after delay', () => {
const callback = jest.fn();
const debounced = debounce(callback, 500);
debounced();
expect(callback).not.toHaveBeenCalled();
jest.advanceTimersByTime(500);
expect(callback).toHaveBeenCalledTimes(1);
});
test('setInterval ticks', () => {
const tick = jest.fn();
setInterval(tick, 1000);
jest.advanceTimersByTime(3500);
expect(tick).toHaveBeenCalledTimes(3);
});
// Run all pending timers
jest.runAllTimers();
// Run only currently pending timers (not nested)
jest.runOnlyPendingTimers();
// Mock Date.now()
jest.setSystemTime(new Date('2024-06-01'));
expect(Date.now()).toBe(new Date('2024-06-01').getTime());
// Restore real timers
afterEach(() => {
jest.useRealTimers();
});
Mock Cheat Sheet
| Method | Purpose | Resets With |
|---|---|---|
jest.fn() | Create standalone mock function | mockClear / mockReset |
jest.mock(module) | Auto-mock entire module | jest.unmock() |
jest.spyOn(obj, method) | Spy on existing method | mockRestore |
jest.useFakeTimers() | Control time-based APIs | useRealTimers() |
jest.clearAllMocks() | Clear call history on all mocks | โ |
jest.resetAllMocks() | Clear + remove implementations | โ |
jest.restoreAllMocks() | Restore all spyOn mocks | โ |