Jest中Mock内部函数时如何确保测试用例独立,避免调用次数统计相互干扰?
解决Jest测试用例间Mock调用记录累加的问题
这个问题的核心原因是:Jest创建的spy/mock函数默认会在测试用例之间保留调用统计信息,所以第二个测试会把第一个测试里的调用次数也计算在内。下面是几种能让测试用例Mock完全独立的方案:
方案1:每个测试后清除所有Mock的调用记录
使用afterEach钩子,在每个测试执行完毕后清除所有Mock的调用次数、参数等记录,这样每个测试的统计都是独立的:
import * as helper from './helper'; // 每个测试用例执行完后,清除所有Mock的调用记录 afterEach(() => { jest.clearAllMocks(); }); test("Test Case 1", ()=> { jest.spyOn(helper, 'refreshInfo').mockImplementationOnce(() => console.log("1")); helper.function2(); expect(helper.refreshInfo).toHaveBeenCalledTimes(1); }) test("Test Case 2", ()=> { jest.spyOn(helper, 'refreshInfo').mockImplementationOnce(() => console.log("2")); helper.function2(); expect(helper.refreshInfo).toHaveBeenCalledTimes(1); })
方案2:恢复Mock到原始函数实现
如果你不仅需要重置调用次数,还希望每个测试后把被Mock的函数恢复成原始实现,可以使用mockRestore:
方式A:在钩子中统一恢复
import * as helper from './helper'; afterEach(() => { // 恢复所有被spyOn的函数到原始实现,同时清除调用记录 jest.restoreAllMocks(); }); test("Test Case 1", ()=> { jest.spyOn(helper, 'refreshInfo').mockImplementationOnce(() => console.log("1")); helper.function2(); expect(helper.refreshInfo).toHaveBeenCalledTimes(1); }) test("Test Case 2", ()=> { jest.spyOn(helper, 'refreshInfo').mockImplementationOnce(() => console.log("2")); helper.function2(); expect(helper.refreshInfo).toHaveBeenCalledTimes(1); })
方式B:单个Mock链式调用mockRestore
你也可以在创建spy的时候直接链式调用mockRestore,让Jest在测试结束后自动恢复这个函数:
test("Test Case 1", ()=> { jest.spyOn(helper, 'refreshInfo') .mockImplementationOnce(() => console.log("1")) .mockRestore(); // 测试结束后自动恢复原始函数 helper.function2(); expect(helper.refreshInfo).toHaveBeenCalledTimes(1); })
方案3:针对单个Mock清除记录
如果不想全局清除,也可以在每个测试结束后单独清除目标Mock的记录:
afterEach(() => { helper.refreshInfo.mockClear(); });
各方法区别说明
jest.clearAllMocks():仅清除调用次数、调用参数等统计信息,不会改变Mock的实现,适合只需要重置计数的场景。jest.restoreAllMocks():会将所有被jest.spyOn创建的Mock恢复为原始函数实现,同时清除调用记录,适合需要完全重置Mock的场景。mockClear()/mockRestore():针对单个Mock操作,更灵活。
内容的提问来源于stack exchange,提问作者Kishan Mishra
相关产品推荐
相关产品推荐

