测试点击函数调用时报错:Attempted to wrap undefined property onClickHandler as function
That error pops up because the onClickHandler you're trying to spy on doesn't exist on Counter.prototype—chances are you defined the method using class fields (arrow function syntax) in your component, which binds the method directly to the component instance instead of the prototype.
Let's break down the problem first
If your Counter component looks something like this:
class Counter extends React.Component { onClickHandler = () => { // Your increment logic here } render() { return <button onClick={this.onClickHandler}>Increment</button>; } }
The arrow function class field attaches onClickHandler directly to each component instance, not the Counter prototype. So when your test tries to access Counter.prototype.onClickHandler, it gets undefined—hence Sinon's error.
Here are two ways to fix this:
Option 1: Switch to a prototype method with manual binding
Modify your component to use a traditional prototype method, and bind this in the constructor:
class Counter extends React.Component { constructor(props) { super(props); this.onClickHandler = this.onClickHandler.bind(this); } onClickHandler() { // Your increment logic here } render() { return <button onClick={this.onClickHandler}>Increment</button>; } }
Now Counter.prototype.onClickHandler exists, and your original test code will work as expected.
Option 2: Spy on the component instance (no component changes needed)
If you don't want to rewrite your component code, spy on the method directly from the mounted component instance instead of the prototype:
it("check counter increment function is called", () => { const sandbox = sinon.createSandbox(); const wrapper = shallow(<Counter />); // Spy on the instance's onClickHandler method const spy = sandbox.spy(wrapper.instance(), "onClickHandler"); // Force an update so the component uses the spied method wrapper.instance().forceUpdate(); wrapper.find("button").simulate("click"); expect(spy.called).toBe(true); sandbox.restore(); });
The forceUpdate() call is crucial here—Enzyme's shallow render doesn't automatically pick up changes to instance methods after the component is created, so we need to trigger an update to make sure the button uses our spied version of onClickHandler.
内容的提问来源于stack exchange,提问作者naveen

