我正在尝试模拟一个返回 promise 的服务,以便我可以验证它是否使用正确的参数调用。调用服务的方式因 state
而异,第一次调用服务会设置 state
。
在 promise 中设置状态时,它不会更新,除非我将断言包装在 setTimeout
中或完全取消 promise。有没有一种方法可以通过简单的 promise 和期望来做到这一点?
我的组件:
class App extends Component {
constructor(props) {
super(props);
this.state = {results: []};
this.service = props.service;
this.load = this.load.bind(this);
}
load() {
if (this.state.results.length === 0) {
this.service.load('state is empty')
.then(result => this.setState({results: result.data}));
} else {
this.service.load('state is nonempty')
.then(result => this.setState({results: result.data}));
}
}
render() {
return (
<div className="App">
<button id="submit" onClick={this.load}/>
</div>
);
}
}
我的测试:
it('Calls service differently based on results', () => {
const mockLoad = jest.fn((text) => {
return new Promise((resolve, reject) => {
resolve({data: [1, 2]});
});
});
const serviceStub = {load: mockLoad};
let component = mount(<App service={serviceStub}/>);
let button = component.find("#submit");
button.simulate('click');
expect(mockLoad).toBeCalledWith('state is empty');
button.simulate('click');
//this assertion fails as the state has not updated and is still 'state is empty'
expect(mockLoad).toBeCalledWith('state is nonempty');
});
如前所述,以下方法有效,但如果有办法解决,我宁愿不包装 expect:
setTimeout(() => {
expect(mockLoad).toBeCalledWith('state is nonempty');
done();
}, 50);
我还可以更改我模拟函数的方式,以消除将起作用的 promise :
const mockLoad = jest.fn((text) => {
return {
then: function (callback) {
return callback({
data : [1, 2]
})
}
}
});
但我只想返回一个 promise 。
最佳答案
出于性能原因,React 批量调用 setState
,所以此时
expect(mockLoad).toBeCalledWith('state is nonempty');
条件
if (this.state.results.length === 0) {
很可能仍然是 true
,因为 data
尚未 添加到 state
。
你最好的选择是
要么使用forceUpdate在第一次和第二次
点击事件
之间。或者将测试分成两个单独的部分,同时在测试之外提取通用逻辑。甚至
it
子句也将变得更具描述性,例如:it('当状态为空时正确调用服务')
用于第一个测试,第二个测试类似。
我赞成第二种方法。
setState() does not always immediately update the component. It may batch or defer the update until later.
阅读更多 here .
关于javascript - 在 Promise 中调用 setState 时 React Jest 测试失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43689765/