You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:11:51