Sinon Spy未触发问题求助(TypeScript+React+Jest+Enzyme)
解决Sinon Spy未捕获React组件touchStartHandler调用的问题
我碰到过好几个类似的情况——明明函数已经执行(控制台都打印了),但Sinon spy的callCount就是显示0。结合你的代码和技术栈,我来帮你拆解问题根源和解决办法:
核心原因:bind时机与Spy绑定顺序冲突
你的代码在constructor里执行了this.touchStartHandler = this.touchStartHandler.bind(this),这一步会生成一个全新的绑定函数。之后在componentDidMount里,你把这个绑定后的函数添加成了事件监听器。如果你的Spy是在组件实例创建完成后才挂载到实例的touchStartHandler上,那实际上你监听的是一个从未被调用的函数——事件触发时执行的是bind生成的旧函数,不是你Spy的版本。
可行解决方案
方案1:Spy组件原型上的方法(最推荐)
因为bind后的函数最终还是会调用原型上的原始方法,所以直接Spy原型上的touchStartHandler就能捕获到所有调用:
import sinon from 'sinon'; import YourComponent from './YourComponent'; import { mount } from 'enzyme'; describe('YourComponent', () => { it('should trigger touchStartHandler on touchstart', () => { // 组件挂载前,先Spy原型上的方法 const touchStartSpy = sinon.spy(YourComponent.prototype, 'touchStartHandler'); const wrapper = mount(<YourComponent />); // 触发touchstart事件(确保选中的是绑定事件的那个div) wrapper.find('div').simulate('touchstart'); expect(touchStartSpy.callCount).to.equal(1); // 测试结束后恢复原型方法,避免影响其他用例 touchStartSpy.restore(); }); });
方案2:在bind前替换实例方法(适合特殊场景)
如果你不想Spy原型方法,可以在组件实例创建但还没执行constructor里的bind逻辑时,手动替换并重新绑定:
it('should trigger touchStartHandler on touchstart', () => { const wrapper = shallow(<YourComponent />); const instance = wrapper.instance(); // 先Spy实例上的原始方法 const touchStartSpy = sinon.spy(instance, 'touchStartHandler'); // 重新绑定并手动调用生命周期添加事件 instance.touchStartHandler = instance.touchStartHandler.bind(instance); instance.componentDidMount(); wrapper.find('div').simulate('touchstart'); expect(touchStartSpy.callCount).to.equal(1); touchStartSpy.restore(); });
额外检查点
- 确认
simulate('touchstart')的目标元素正确:如果divElement是通过ref获取的特定div,可以用wrapper.instance().divElement拿到这个DOM元素再触发事件。 - 排查是否有其他代码在组件更新时重新绑定了事件,覆盖了Spy的方法。
内容的提问来源于stack exchange,提问作者nina
相关产品推荐
相关产品推荐

