问题
I have the following parent component:
import React, { Fragment } from 'react';
export class Parent extends Component {
constructor(props) {
super(props);
this.state = {
show: false,
};
}
onClick = () => {
// working
}
render() {
return (
<Fragment>
<Child handleClick={this.onClick} />
</Fragment>
);
}
}
I need to check if callback fired in Child component, onClick method will be fired in Parent component. I wrote such a test:
test("check callback fire", () => {
let mockFn = jest.fn();
Parent.prototype.onClick = mockFn;
let wrapper = shallow(<Parent />);
wrapper.find('Child').props().handleClick();
expect(mockFn).toHaveBeenCalled();
});
and I got an error
Expected mock function to have been called, but it was not called.
How can I do that properly with jest and enzyme? Is it possible?
回答1:
Your onClick function is on the object itself, not the prototype. You have to modify the object instance.
let mockFn = jest.fn();
let wrapper = shallow(<Parent />);
wrapper.find('Child').props().handleClick = mockFn;
wrapper.find('Child').props().handleClick();
expect(mockFn).toHaveBeenCalled();
Having said that, you are calling onClick yourself, so it doesn't make sense to test that it was called.
You should test its effect, for example, part of the DOM is not showing.
You could also test that they component's state updates correctly, that is {show: false}
回答2:
the problem comes from the declaration of the onClick
method, if you declare your function like this
onClick() {}
instead of
onClick = () => {}
your test should work because onClick
will be present in the Parent.prototype
object, note that this
keyword in the onClick
method will no longer refers to the class instance.
If you need to use arrow function (to get the correct value of this
), you could modify your test :
test("check callback fire", () => {
let mockFn = jest.fn();
let wrapper = shallow(<Parent />);
wrapper.instance().onClick = mockFn;
wrapper.find('Child').props().handleClick();
expect(mockFn).toHaveBeenCalled();
});
Using onClick = () => {}
in the Parent
class will not add the property to Parent.prototype
, in fact it will declare an instance variable like this :
class Parent {
constructor() {
super();
this.onClick = () => {}
}
}
By the way, the presence of Fragment
inside your render
method seems to be useless, you could remove it
render() {
return <Child handleClick={this.onClick} />;
}
回答3:
I suggest doing this with two tests:
- A unit test for the
Child
component that asserts itsonClick
prop is called when appropriate. - A unit test for the
Parent
that it properly sets theonClick
prop of itsChild
when rendered.
With these two tests, you will be alerted if either of these pieces fails.
来源:https://stackoverflow.com/questions/56067131/how-test-callback-click-in-child-component-that-was-passed-from-parent-component