我正在尝试使用Enzyme / Jest测试事件处理程序中的react组件,但是从未调用过我的间谍函数...
我的组件有一个带ID的div,我正在用它来查找dom elem
render() {
return (
<div>
<Top
{...this.props}
/>
<div
id = 'keyboard_clickable'
onClick = {this._handleClick}
style= {styles.main}>
{this._showKeyBoard()}
</div>
<input onChange = {() => {}}/>
</div>
);
}
}
我的测试
describe('onclick function is called ...', () => {
it.only('spyOn', () => {
const spy = jest.fn()
const wrapper = shallow(
<Keyboard
_getData = { () => {} }
_erase = { () => {} }
_get_letters = { () => {} }
_createWord = { () => {} }
_modeSwitch = { () => {} }
onClick = { spy }
/>
)
wrapper.find('#keyboard_clickable').simulate('click', {
target:{
parentElement:{ id: 5 },
id:6
}
})
expect(spy).toHaveBeenCalled();
})
})
我的HandleClick
_handleClick = e => {
let parent = e.target.parentElement;
if(e.target.id || (!isNaN(parent.id) && parent.id > 0) ) {
this.props._getData(e.target.id || e.target.parentElement.id)
this.setState({status:'ok'})
}else{
this.setState({status:'Use numbers between 2 and 9'},()=>{
return alert(this.state.status)
})
}
}
测试输出
Expected mock function to have been called, but it was not called.
答案 0 :(得分:2)
要测试事件处理程序是否被调用,您必须用模拟函数替换事件处理程序。一种方法是扩展组件类:
class TestKeyboard extends Keyboard {
constructor(props) {
super(props)
this._handleClick = this.props._handleClick
}
}
describe('onclick function is called ...', () => {
it.only('spyOn', () => {
const spy = jest.fn()
const wrapper = shallow(
<TestKeyboard
_getData = { () => {} }
_erase = { () => {} }
_get_letters = { () => {} }
_createWord = { () => {} }
_modeSwitch = { () => {} }
_handleClick = { spy }
/>
)
wrapper.find('#keyboard_clickable').simulate('click', {
target:{
parentElement:{ id: 5 },
id:6
}
})
expect(spy).toHaveBeenCalled();
})
})
道具_handleClick
替换了Keyboard._handleClick,因此当onClick
在被点击的元素中触发时被调用。
如果需要让事件处理程序执行并进行测试,可以使用jest.spyOn
。我发现这种方法更复杂,但更灵活。
import { mount } from 'enzyme'
describe('onclick function is called ...', () => {
it.only('spyOn', () => {
const wrapper = mount(
<Keyboard
_getData = { () => {} }
_erase = { () => {} }
_get_letters = { () => {} }
_createWord = { () => {} }
_modeSwitch = { () => {} }
/>
)
const spy = jest.spyOn(wrapper.instance(), '_handleClick')
wrapper.instance().forceUpdate()
wrapper.find('#keyboard_clickable').simulate('click', {
target:{
parentElement:{ id: 5 },
id:6
}
})
expect(spy).toHaveBeenCalled();
})
})
请注意,这在使用浅层渲染时将失败,因此您必须改为使用ases.mount。
答案 1 :(得分:0)
似乎可以在浅层渲染中用酶模拟点击确实有效,但前提是我必须像Jemi的解决方案那样使用forceUpdate()。
示例:
beforeEach(() => {
wrapper = shallow(<VehicleDamage handleSubmit={mockFunction} onPrevClick={mockFunction} />);
});
it('handlePrevClick is called on click', function() {
const spyHandlePrevClick = jest.spyOn(wrapper.instance(), 'handlePrevClick');
wrapper.instance().forceUpdate(); // I assume required to assign mocked function
let buttonContainer = wrapper.find('ButtonContainer').dive();
let button = buttonContainer.find('Button').at(0);
button.simulate('click', {
preventDefault: () => jest.fn()
});
expect(spyHandlePrevClick).toHaveBeenCalled();
});