ReactJS使用Jest+Enzyme测试spyOn监听函数调用次数为0如何解决
问题原因
- 引用不一致:测试文件导入的
DEMO和App组件内部引用的DEMO不是同一份模块实例,通常是导入路径错误、混淆命名导入/默认导入导致,你监听的是另一个对象的方法,自然无法捕获App内的调用。 - shallow渲染事件模拟失效:部分版本的Enzyme shallow渲染对
simulate事件模拟的支持存在缺陷,调用simulate('click')没有实际触发按钮绑定的getAlert方法,自然不会触发DEMO.test.hi的调用。 - spy时机错误:如果在监听
DEMO.test.hi之前就已经完成了App组件的导入和初始化,组件内部的getAlert引用的是未被监听的原生方法,会导致监听失效。
解决方法
按照以下步骤依次排查修改即可:
- 确认导入一致性:测试文件中
DEMO的导入路径、导入方式必须和App组件完全一致,比如App内使用import { DEMO } from './config',测试文件也要使用完全相同的导入语句,不能写错路径或者误用默认导入。 - 替换事件触发方式:放弃Enzyme的
simulate方法,直接获取按钮的onClick属性手动调用,规避模拟事件的兼容性问题,修改后的测试代码如下:
it('should trigger calls', () => { const spyOnFun = jest.spyOn(DEMO.test, 'hi'); const wrapper = shallow(<App/>); // 直接调用onClick方法,替代simulate wrapper.find('button').prop('onClick')(); expect(spyOnFun).toHaveBeenCalledTimes(1); // 测试结束后恢复原方法,避免影响其他用例 spyOnFun.mockRestore(); });
- 如果以上修改仍然无效,可以调整spy时机,在测试文件顶部就完成对
DEMO.test.hi的监听,再导入App组件;也可以直接使用jest.mockmock整个DEMO模块:
// 测试文件最顶部先mock DEMO模块 jest.mock('./你的DEMO文件路径', () => ({ DEMO: { test: { hi: jest.fn() } } })); import { DEMO } from './你的DEMO文件路径'; import App from './App'; it('should trigger calls', () => { const wrapper = shallow(<App/>); wrapper.find('button').prop('onClick')(); expect(DEMO.test.hi).toHaveBeenCalledTimes(1); });
- 如果是React版本过高导致Enzyme兼容问题,建议降级React到17及以下适配Enzyme,或者替换测试框架为React Testing Library。
内容的提问来源于stack exchange,提问作者Asking
相关产品推荐
相关产品推荐

