使用Enzyme/Jest测试React组件点击事件时遇expect(jest.fn())报错
解决Enzyme/Jest测试中模拟点击触发props函数失败的问题
看起来你的测试遇到了两个小问题:一是Sinon Spy和Jest断言的兼容冲突,二是点击事件的触发目标选择不太妥当。咱们一步步来解决:
问题根源拆解
错误提示jest.fn() value must be a mock function or spy. Received: function: [Function proxy],本质是你用了Sinon创建的Spy函数,却试图用Jest内置的toHaveBeenCalled()断言去验证它——Jest的这个断言只认自己生成的Mock函数,对Sinon的Spy不兼容。另外,你模拟点击的是<i>图标元素,但组件的onClick事件其实绑定在父级<a>标签上,虽然事件冒泡理论上能触发父元素事件,但直接触发事件绑定的元素更稳妥,能避免不必要的意外。
两种可行解决方案
方案1:改用Jest原生Mock函数(推荐)
放弃Sinon,直接用Jest自带的jest.fn()创建Mock函数,和Jest的断言体系完美兼容:
import expect from 'expect'; import React from 'react'; import { shallow } from 'enzyme'; import ToggleSideNavComponent from './ToggleSideNavComponent'; function setup() { // 用Jest原生Mock替代Sinon Spy const props = { handleSideNavToggle: jest.fn() }; return { props: props, wrapper: shallow(<ToggleSideNavComponent {...props} />) }; } describe('ToggleSideNavComponent', () => { it('should render menu icon and trigger toggle function on click', () => { const { props, wrapper } = setup(); // 直接找到绑定onClick的<a>元素模拟点击 wrapper.find('#toggle_sidebar_btn').simulate('click'); // Jest断言可以正常识别自己的Mock函数 expect(props.handleSideNavToggle).toHaveBeenCalled(); // 验证菜单图标存在 expect(wrapper.find('#menu').length).toBe(1); }); });
方案2:继续使用Sinon,改用Sinon专属断言
如果你习惯用Sinon,需要换成Sinon自己的断言方法来检查Spy是否被调用:
import expect from 'expect'; import React from 'react'; import { shallow } from 'enzyme'; import ToggleSideNavComponent from './ToggleSideNavComponent'; import sinon from 'sinon'; function setup() { const props = { handleSideNavToggle: sinon.spy() }; return { props: props, wrapper: shallow(<ToggleSideNavComponent {...props} />) }; } describe('ToggleSideNavComponent', () => { it('should render menu icon and trigger toggle function on click', () => { const { props, wrapper } = setup(); wrapper.find('#toggle_sidebar_btn').simulate('click'); // 使用Sinon的断言方法验证Spy调用 sinon.assert.calledOnce(props.handleSideNavToggle); expect(wrapper.find('#menu').length).toBe(1); }); });
额外小贴士
- 尽量直接模拟绑定了
onClick事件的元素,不要选择它的子元素,避免事件冒泡失效等意外情况导致测试不稳定。 - 新版本Jest的Mock工具和自身生态(断言、覆盖率统计等)整合度更高,优先使用原生Mock能减少第三方依赖带来的兼容问题。
内容的提问来源于stack exchange,提问作者Sinha
相关产品推荐
相关产品推荐

