Jest Mock 模式
jest.fn() — Mock 函数
const mockFn = jest.fn();
mockFn('hello');
expect(mockFn).toHaveBeenCalledWith('hello');
expect(mockFn).toHaveBeenCalledTimes(1);
// 设置返回值
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); // 默认回退值
// Mock 实现
const greet = jest.fn((name) => `你好,${name}!`);
// 检查调用记录
console.log(mockFn.mock.calls); // [[arg1, arg2], ...]
console.log(mockFn.mock.results); // [{ type: 'return', value: ... }]
// 重置
mockFn.mockClear(); // 清空调用记录
mockFn.mockReset(); // 同时移除实现
mockFn.mockRestore(); // 仅适用于 spyOn
jest.mock() — 模块 Mock
// 自动 mock 整个模块
jest.mock('./utils/api');
import { fetchUser } from './utils/api';
// fetchUser 现在是 jest.fn()
// 部分 mock — 保留真实实现
jest.mock('./utils/helpers', () => ({
...jest.requireActual('./utils/helpers'),
formatDate: jest.fn(() => '2024-01-01'),
}));
// 工厂函数 mock(在 import 之前执行)
jest.mock('axios', () => ({
default: {
get: jest.fn(),
post: jest.fn(),
},
}));
import axios from 'axios';
(axios.get as jest.Mock).mockResolvedValue({ data: { id: 1 } });
afterEach(() => {
jest.clearAllMocks();
});
jest.spyOn() — 监听真实方法
import * as mathUtils from './mathUtils';
// 监听而不改变实现
const spy = jest.spyOn(mathUtils, 'add');
mathUtils.add(2, 3);
expect(spy).toHaveBeenCalledWith(2, 3);
// 临时覆盖实现
jest.spyOn(console, 'error').mockImplementation(() => {});
// 监听类方法
class UserService {
async getUser(id: string) { /* ... */ }
}
const service = new UserService();
const getSpy = jest.spyOn(service, 'getUser').mockResolvedValue({ id: '1', name: 'Alice' });
afterEach(() => {
jest.restoreAllMocks();
});
手动 Mock — __mocks__ 目录
// __mocks__/fs.js — Node 内置模块手动 mock
const fs = jest.createMockFromModule('fs');
fs.readFileSync = jest.fn((filePath) => {
if (MOCK_FILE_INFO[filePath]) return MOCK_FILE_INFO[filePath];
throw new Error(`文件未找到: ${filePath}`);
});
module.exports = fs;
// 本地模块:__mocks__ 放在模块旁边
// src/utils/__mocks__/database.ts
export const query = jest.fn().mockResolvedValue([]);
export const close = jest.fn();
定时器 Mock — Fake Timers
jest.useFakeTimers();
test('防抖在延迟后触发', () => {
const callback = jest.fn();
const debounced = debounce(callback, 500);
debounced();
expect(callback).not.toHaveBeenCalled();
jest.advanceTimersByTime(500);
expect(callback).toHaveBeenCalledTimes(1);
});
// 模拟 Date.now()
jest.setSystemTime(new Date('2024-06-01'));
afterEach(() => {
jest.useRealTimers();
});
Mock 速查表
| 方法 | 用途 | 重置方式 |
|---|---|---|
jest.fn() | 创建独立 mock 函数 | mockClear / mockReset |
jest.mock(module) | 自动 mock 整个模块 | jest.unmock() |
jest.spyOn(obj, method) | 监听已有方法 | mockRestore |
jest.useFakeTimers() | 控制时间相关 API | useRealTimers() |
jest.clearAllMocks() | 清空所有 mock 调用记录 | — |
jest.restoreAllMocks() | 还原所有 spyOn mock | — |