如何在Jest配置resetAllMocks的场景下重置模块指定方法的mock?
Jest配置resetAllMocks后稳定mock react-router指定方法的解决方案
问题根因
jest.mock是编译期执行API,会被提升至所有import语句前运行,写在beforeEach等运行时钩子中不会生效,对应方案2失效。- ES模块默认导出为只读属性,未提前mock模块的前提下直接调用
jest.spyOn修改导出属性会抛出重定义错误,对应方案4失效。 - 调用
jest.mock('react-router')不传工厂函数会将整个模块所有导出替换为无默认实现的空mock函数,原有功能全部被覆盖,对应方案3失效。 - 顶层直接为mock的hook设置固定返回值时,
resetAllMocks会清除mock函数的返回值配置,导致第二个测试用例调用对应hook返回undefined,对应方案1失效。
可行实现方案
核心逻辑为:顶层mock时将hook的执行指向独立的mock函数,每次测试前重新设置mock函数的返回值,避开resetAllMocks的影响。
import * as ReactRouter from 'react-router'; // 提前声明对应方法的mock函数 const mockPush = jest.fn(); const mockUseHistory = jest.fn(); const mockUseRouteMatch = jest.fn(); // 编译期全局mock react-router,保留原有功能,仅将指定hook指向我们声明的mock函数 jest.mock('react-router', () => ({ ...jest.requireActual('react-router'), useHistory: () => mockUseHistory(), useRouteMatch: () => mockUseRouteMatch(), })); // 每次测试前重新设置mock函数的返回值 beforeEach(() => { mockUseHistory.mockReturnValue({ push: mockPush }); mockUseRouteMatch.mockReturnValue({ url: '' }); }); // 保持原有重置mock的配置 afterEach(() => { jest.resetAllMocks(); });
验证说明
该方案下所有测试用例都会获取到hook的正确返回值,mockPush的调用记录会在每个测试用例结束后被清空,不会出现用例之间的数据污染。
内容的提问来源于stack exchange,提问作者Gergő Horváth
相关产品推荐
相关产品推荐

