如何使用Jest模拟原生JavaScript方法?如何测试JSON.stringify调用次数?
如何用Jest模拟原生JavaScript方法(以JSON.stringify为例)
当然可以用Jest实现!模拟原生JS方法是Jest的核心能力之一,我来一步步带你搞定JSON.stringify调用次数的测试,顺便把需要注意的细节也说清楚。
核心步骤:监听+断言+清理
1. 用jest.spyOn监听原生方法
Jest的jest.spyOn函数专门用来监听对象的方法——哪怕是JSON这种全局对象也完全没问题。它会帮你保存原方法的引用,方便后续恢复,比直接替换方法要安全得多。
示例代码:
// 在单个测试用例内或者beforeEach钩子中创建监听 const stringifySpy = jest.spyOn(JSON, 'stringify');
2. 执行被测代码并断言调用次数
假设你有一个依赖JSON.stringify的函数,比如:
// 这是你要测试的业务函数 function serializeUser(user) { return JSON.stringify({ id: user.id, name: user.name }); }
对应的测试用例可以这么写:
test('serializeUser调用JSON.stringify恰好1次', () => { // 1. 监听JSON.stringify const stringifySpy = jest.spyOn(JSON, 'stringify'); // 2. 执行被测函数 serializeUser({ id: 1, name: 'Alice' }); // 3. 断言调用次数 expect(stringifySpy).toHaveBeenCalledTimes(1); // 进阶:还可以断言调用时的参数是否正确 expect(stringifySpy).toHaveBeenCalledWith({ id: 1, name: 'Alice' }); });
3. 清理模拟,避免影响其他测试
如果不清理模拟,这个被篡改的JSON.stringify会影响后续的测试用例。有几种简单的清理方式:
- 单个测试用例后恢复原方法:
test('...', () => { const stringifySpy = jest.spyOn(JSON, 'stringify'); // 测试逻辑... stringifySpy.mockRestore(); // 恢复原方法 });
- 全局统一清理(推荐):在测试文件顶部添加钩子,自动清理所有模拟:
afterEach(() => { jest.restoreAllMocks(); // 恢复所有被spyOn监听的方法 // 或者用jest.clearAllMocks()只清空调用记录,不恢复原方法,根据需求选择 });
进阶:自定义模拟返回值
如果你不想让JSON.stringify真的执行序列化逻辑(比如想要固定返回值),可以用mockImplementation或者mockReturnValue自定义它的行为:
test('自定义JSON.stringify的返回值', () => { const stringifySpy = jest.spyOn(JSON, 'stringify').mockReturnValue('{"mock":"data"}'); const result = serializeUser({ id: 1, name: 'Alice' }); expect(result).toBe('{"mock":"data"}'); // 验证返回的是模拟值 expect(stringifySpy).toHaveBeenCalledTimes(1); });
避坑提醒
别直接替换全局方法(比如JSON.stringify = jest.fn()),这种方式会彻底覆盖原方法,而且很难干净地恢复,容易导致测试用例之间的污染。jest.spyOn是更安全的选择,它会自动保留原方法的引用。
内容的提问来源于stack exchange,提问作者Rupert
相关产品推荐
相关产品推荐

