Jest+Enzyme. Cannot read property '_isMockFunc

2019-06-20 14:07发布

问题:

I have a serious problem with testing methods of my main component. My actual test after many retries still don't work and looks like this:

describe('<App />:', () => {
    beforeEach(() => {
        wrapper = mount(<Provider store={store}><App /></Provider>);
    });
    describe('Interaction:', () => {
        it('should call ArrowDown()', () => {
            const instance = wrapper.instance();
            spy = jest.spyOn(instance, 'ArrowDown');
            instance.forceUpdate();
            wrapper.simulate('keyDown', {key: 'Arrow down'});
            expect(spy).toHaveBeenCalled();
        });
    }); 
});

What I get from the console is:

TypeError: Cannot read property '_isMockFunction' of undefined

Other tests like snapshoting or finding other components inside of App works fine. I was searching for simillar problems but solutions I have found do not work as you can see. Please for help.

PS: Same error when I use prototype:

describe('<App />:', () => {
    beforeEach(() => {
        wrapper = mount(<Provider store={store}><App /></Provider>);
    });
    describe('Interaction:', () => {
            it('should call ArrowDown()', () => {
            spy = jest.spyOn(App.prototype, 'ArrowDown');
            wrapper = mount(<Provider store={store}><App /></Provider>);
            wrapper.simulate('keyDown', {key: 'Arrow down'});
            expect(spy).toHaveBeenCalled();
        });
    }); 
});

回答1:

It looks like jest.SpyOn(App.prototype, 'ArrowDown') is the line causing your issue. I'm not exactly sure why without looking at your App declaration but I would point out that this isn't how I would go about testing, and I'd venture that maybe this isn't the way that Jest/Enzyme is intended to be used.

In this test you're not actually testing anything other than the fact that React has successfully bound a keypress to a component function, which doesn't really exercise anything meaningful about your code, or any particular logic. I would normally write a test that simulates a button click and then inspects the new DOM state to check that the button click had the desired effect.

If there was a service call involved, I'd probably spy on the service layer, check that it was being called correctly and return a controlled value, then make sure that the DOM was in the correct state. Spying on individual component methods isn't really necessary when you do things this way.