[英]How to wait for an async call to finish in component's mount callback before unit testing it?
[英]JS unit testing using enzyme: how to wait for setState within component's method to finish before proceeding with test case
我有一個帶有方法doSomething
的組件MyComponent
更新狀態,以及基於這些狀態呈現子組件的renderChildren
:
class MyComponent extends Component {
constructor(props) {
super(props);
...
this.state = {
renderChildA: true,
renderChildB: false,
};
}
doSomething = (params) => {
// Do something...
this.setState({
renderChildA: false,
renderChildB: true,
});
}
renderChildren = () => {
const { renderChildA, renderChildB } = this.state;
if (renderChildA) {
return <ChildComponentA />;
} else if (renderChildB) {
return <ChildComponentB />;
}
}
render() {
return (
<div>
{this.renderChildren()}
...
</div>
);
}
}
注意:該組件也連接到 Redux,但已被簡化。
對於單元測試,我調用doSomething
並驗證ChildComponentB
是否可見:
test('doSomething should trigger ChildComponentB to pop up', () => {
const wrapper = shallow(
<MyComponent
...
/>,
).dive();
wrapper.instane().doSomething(params); // assume params is defined
const childComponentB = wrapper.find('ChildComponentB');
expect(childComponentB).toHaveLength(1);
});
但是,上面的測試用例失敗了:
my-component.test.jsx > Some test group name > doSomething should trigger ChildComponentB to pop up
expect(received).toHaveLength(length)
Expected value to have length:
1
Received:
// Some giant JSON object
recevied.length:
0
xxx | const childComponentB = wrapper.find('ChildComponentB');
xxx | expect(childComponentB).toHaveLength(1);
xxx | });
根據日志記錄,我看到在測試用例中的expect
語句之后觸發了doSomething
中的setState
。 我懷疑這是因為setState
是異步的,但我不知道解決方法(除了setTimeout
)。
您可以嘗試手動更新組件以獲取最新狀態:
wrapper.instance().doSomething(params); // assume params is defined
wrapper.update();
const childComponentB = container.find('ChildComponentB');
expect(childComponentB).toHaveLength(1);
更多信息: https : //airbnb.io/enzyme/docs/api/ShallowWrapper/update.html
不確定這是否有效,但讓我們嘗試將doSomething
函數更新為。
doSomething = (params) => {
this.setState({
renderChildA: false,
renderChildB: true,
},() => this.renderChildren());
}
找到了一個相當簡單的解決方案。 使用Async/Await
:
test('doSomething should trigger ChildComponentB to pop up', async() => {
const wrapper = shallow(
<MyComponent
...
/>,
).dive();
await wrapper.instane().doSomething(params);
const childComponentB = wrapper.find('ChildComponentB');
expect(childComponentB).toHaveLength(1);
});
只需添加async
並await
test('describe your test', async() => { // add async here
const wrapper = shallow(
<MyComponent
...
/>,
).dive();
await wrapper.instane().doSomething(params); // add wait here
const childComponentB = wrapper.find('ChildComponentB');
expect(childComponentB).toHaveLength(1)
});
it('check List component for column list', async () => {
#ur code for re-render stuff
await new Promise(resolve => setTimeout(resolve, 0)); // wait for response
# this will sync ur wrapper with latest tree change
wrapper = wrapper.update();
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.