我的 componentDidMount 中有一个 Action ,它在 30000 毫秒后从 Reddit 获取图像。我想测试这个但无法弄清楚?!?!有什么建议吗?
componentDidMount() {
this.getHumorEvery(30000)
}
getHumorEvery = async (ms) => {
await this.props.getHumor()
return setInterval(() => {
this.props.getHumor()
}, ms)
因此 getHumor() 会立即得到调用。然后在 30000 毫秒后再次调用它,依此类推。
然后我的测试...
it('should refetch images every 30000 ms', () => {
const clock = sinon.useFakeTimers();
const getHumorSpy = sinon.spy();
renderComponent(requiredProps({ getHumor: getHumorSpy }));
clock.tick(30000)
sinon.assert.calledTwice(getHumorSpy)
})
测试失败,因为 getHumor 只被调用了一次。 setInterval() 永远不会被解雇?
最佳答案
在 promises 上调用 then 并在异步函数中调用 await 为事件循环排队代码,该事件循环在当前同步代码完成且时钟滴答作响之前不会执行。同样,setTimeout 通常将代码添加到队列中,该队列也必须等到下一个时钟滴答。
Sinon fake timers “是 setTimeout 和 friend 的同步实现”,它们“覆盖全局函数”并管理使用 setTimeout 和类似全局变量排队的代码,并在模拟时钟滴答时同步调用它。
仍在为事件循环排队的代码与之前为事件循环排队但现在被同步调用的代码之间的这种断开可能会导致问题(如 this 和 this )。
这些问题通常可以通过插入事件循环的手动循环来解决,以允许队列中的任何未决代码在同步模拟时钟滴答之前执行。
在这种情况下,将测试转换为异步函数并在已解决的 Promise 上调用 await 使队列中的待处理代码有机会在同步时钟滴答之前运行,从而允许代码按预期运行并正确断言:
it('should refetch images every 30000 ms', async () => {
const clock = sinon.useFakeTimers();
const getHumorSpy = sinon.spy();
renderComponent(requiredProps({ getHumor: getHumorSpy }));
// let event loop cycle
await Promise.resolve();
clock.tick(30000);
sinon.assert.calledTwice(getHumorSpy);
})
关于reactjs - 使用 sinon.fakeTimers 测试 setInterval() 不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51526312/