Can't spy on an event handler even though I can spy on other methods

寵の児 提交于 2019-12-11 01:07:22

问题


I want to test an event handler in React using Jest/Jasmine/Enzyme.

MyComponent.js:

import React from 'react';
class MyComponent extends React.Component {
    constructor(props) {
        super(props);
        this.clickHandler = this.clickHandler.bind(this);
        this.otherMethod  = this.otherMethod .bind(this);
    }

    clickHandler() { this.otherMethod(); }
    otherMethod() {}

    render() { return <div onClick={this.clickHandler}/>; }
}
export default MyComponent;

MyComponent.test.js:

import React from 'react';
import {mount} from 'enzyme';
import MyComponent from './MyComponent';

it('should work', () => {
    const componentWrapper = mount(<MyComponent/>);
    const component = componentWrapper.get(0);

    spyOn(component, 'otherMethod' ).and.callThrough();
    spyOn(component, 'clickHandler').and.callThrough();

    componentWrapper.find('div').simulate('click');

    expect(component.otherMethod ).toHaveBeenCalled(); // works
    expect(component.clickHandler).toHaveBeenCalled(); // does not work
});

In spite of the fact that I think I'm spying on the two component methods identically, one of them (for otherMethod) works while the other (for clickHandler) does not. I clearly am calling clickHandler as otherMethod wouldn't be called if I wasn't, but toHaveBeenCalled isn't being picked up for clickHandler somehow. Why?

I understand that I don't really have to use either .bind(this) or .and.callThrough() on otherMethod but I use both just to treat the two methods identically and using them on otherMethod shouldn't actually make any difference.

This other SO answer states that I have to spy on a function before attaching it as a listener. If this is my problem then I don't know how to resolve it: The spyOn syntax requires the object that the method is a property of (component in this case) but using component requires prior mounting of MyComponent which forces me to attach the listener first.

It may be relevant that my code uses React (and thus I include reactjs as a question tag) but somehow I doubt it.


回答1:


For this kind of tests, the common path is to call your handler methods on your component instance instead of simulating the event.

You can be sure the onClick prop is test by the React team, what you can check is what happens when "they" call your handler.

This also allows you to use shallow rendering which at least for me is much faster. You can get a reference to the instance easily with the instance() method in your wrapper, and you can then call your handler and spy on whatever you want.

const wrapper = mount(<MyComponent />)
const instance = wrapper.instance()
instance.clickHandler()
//assert whatever

In fact, probably attaching your spies to the instance`s methods (that have already been binded) will do the trick as well. :)

http://airbnb.io/enzyme/docs/api/ReactWrapper/instance.html

Hope it helps!



来源:https://stackoverflow.com/questions/42016405/cant-spy-on-an-event-handler-even-though-i-can-spy-on-other-methods

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!