创建 javascript mock 的核心是控制依赖行为、隔离测试边界、保持可预测性;按需模拟关键属性与方法,可用对象字面量、class、jest.mock()、jest.spyon() 或工厂函数实现。

为复杂对象创建 JavaScript Mock,核心是控制依赖行为、隔离测试边界、保持可预测性。不追求“完全仿造真实对象”,而是按测试场景需要,精准地模拟关键属性、方法和交互逻辑。
用类或对象字面量手动构造基础 Mock
适合结构明确、行为简单的复杂对象(如配置对象、DTO、轻量服务实例)。
- 直接返回带必要属性和存根方法的对象:
const mockUser = {
id: 123,
name: 'test-user',
profile: { avatar: '/mock.png', bio: 'mock bio' },
getRoles: jest.fn().mockReturnValue(['user']),
toJSON: jest.fn().mockReturnValue({ id: 123, name: 'test-user' })
};- 若需继承或原型链行为,可用
class构建,并在实例上挂载 mock 方法:
class MockApiClient {
constructor() {
this.request = jest.fn();
}
get = this.request.mockResolvedValue({ data: { id: 1 } });
post = this.request.mockResolvedValue({ data: { ok: true } });
}用 Jest 的 jest.mock() 自动替换模块级复杂对象
适用于依赖外部 SDK、工具类或单例服务(如 Axios、localStorage、自定义 DatabaseClient)。
- 在测试文件顶部模拟整个模块,返回定制的 mock 实例:
// __mocks__/db-client.js
const mockQuery = jest.fn();
const mockTransaction = jest.fn().mockImplementation(() => ({
query: mockQuery,
commit: jest.fn(),
rollback: jest.fn()
}));
<p>module.exports = jest.fn().mockImplementation(() => ({
query: mockQuery,
transaction: mockTransaction,
close: jest.fn()
}));</p>- 在测试中启用:
jest.mock('../db-client');
const DbClient = require('../db-client');
<p>test('calls query with correct SQL', () => {
const client = new DbClient();
client.query('SELECT <em> FROM users');
expect(client.query).toHaveBeenCalledWith('SELECT </em> FROM users');
});</p>用 jest.spyOn() 部分拦截 + 真实对象增强
当对象大部分行为可复用,仅需替换少数方法(如网络调用、时间相关、副作用方法)时最实用。
- 保留原对象结构与非 mock 方法,只劫持目标函数:
const realService = new PaymentService();
const spy = jest.spyOn(realService, 'charge').mockRejectedValue(new Error('Declined'));
<p>// 测试异常流程,其余方法(如 validateCard、logAttempt)仍走真实逻辑
await expect(realService.processOrder(order)).rejects.toThrow('Declined');</p><p>spy.mockRestore(); // 清理</p>- 配合
mockImplementationOnce可模拟多步状态(如首次失败、重试成功):
spy.mockImplementationOnce(() => Promise.reject(new Error('Timeout')))
.mockImplementationOnce(() => Promise.resolve({ txId: 'tx-123' }));用工厂函数动态生成带状态的 Mock 实例
适合需多次创建不同状态对象的场景(如测试表单验证、状态机、缓存策略)。
- 封装可配置的 mock 构造逻辑:
const createMockCache = ({ hit = true, maxAge = 300 } = {}) => ({
get: jest.fn().mockImplementation((key) =>
hit ? { value: `cached-${key}`, expiresAt: Date.now() + maxAge * 1000 } : undefined
),
set: jest.fn(),
has: jest.fn().mockReturnValue(hit)
});
<p>test('returns cached value when hit', () => {
const cache = createMockCache({ hit: true });
expect(cache.get('token')).toEqual({ value: 'cached-token', expiresAt: expect.any(Number) });
});</p>Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











