我有这个组件(简化版):
export default class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: false,
data: {}
};
}
componentDidUpdate(prevProps, prevState) {
if(this.props.time && this.props.time !== prevProps.time){
this.setState({
isLoading: true
})
fetch(...).then(data => {
this.setState({
data: data
isLoading:false
}
}
}
render(){
{isLoading, data} = this.state;
return (isLoading ? /*show spinner*/ : /* show data*/);
}
}
此组件有效:它在获取数据时显示微调器,然后显示数据。
我正在尝试使用jest和酶来测试它:
test('Mounted correctly', async() => {
let myComponent = mount(<MyComponent time='01-01-18'/>);
myComponent.setProps({time: '02-01-18'}); //necessary to call componentDidUpdate
expect(myComponent.state()).toMatchSnapshot();
}
据我所知,为了致电componentDidUpdate
,您必须致电setPros
(link)。但是,在调试器之后,当命中时调用结束:
this.setState({
isLoading: true
})
这是预期的,问题是快照是:
Object {
"isLoading": true
"data": {}
}
当然,这是我不想要的东西。我该如何解决这个问题?
更新:我找到了一个(难看的)解决方案!
问题在于我们要测试的是setState
已完成:
this.setState({
data: data
isLoading:false
}
现在,即使设置await myComponent.setProps({time: '02-01-18'});
(如其中一个答案中所建议的),也不会发生这种情况,因为它不会等待上述setState
创建的新异步调用。
我找到的唯一解决方案是将回调函数传递给props
并在setState
完成后调用它。回调函数包含我们想要的expect
!
所以这是最终结果:
test('Mounted correctly', async() => {
let myComponent = mount(<MyComponent time='01-01-18'/>);
const callBackAfterLastSetStateIsCompleted = () => {
expect(topAsins.state()).toMatchSnapshot();
}
myComponent.setProps({time: '02-01-18', testCallBack: callBackAfterLastSetStateIsCompleted}); //necessary to call componentDidUpdate
expect(myComponent.state()).toMatchSnapshot();
}
将组件代码修改为:
this.setState({
data: data
isLoading:false
},this.props.testCallBack);
但是,正如您所看到的,我正在修改生产中的组件仅用于测试目的,这是非常丑陋。
现在,我的问题是:我该如何解决这个问题?
答案 0 :(得分:1)
您需要在此处进行测试,只需使用async/await
test('Mounted correctly', async () => {
let myComponent = mount(<MyComponent time='01-01-18'/>);
await myComponent.setProps({time: '02-01-18'}); //necessary to call componentDidUpdate, await used to wait for async action in componentDidUpdate
expect(myComponent.state()).toMatchSnapshot();
}