【问题标题】:Testing setInterval() with sinon.fakeTimers not working?用 sinon.fakeTimers 测试 setInterval() 不起作用?
【发布时间】:2018-07-25 19:26:26
【问题描述】:

我的 componentDidMount 中有一个动作,它在 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() 永远不会被解雇?

【问题讨论】:

  • 你的 setInterval 回调是否被调用过?如果是,this.props.getHumor是在回调中定义的吗,你确定是sinon spy吗?
  • 是的,如果您在调用 setInterval 之前使用 console.log(setInterval),然后将另一个 console.log() 放入 setTimeout 中,然后运行测试,结果是...... 1) setInterval 注销已存根的 setInterval 2) setInterval 中的 console.log() 永远不会被注销因此,似乎是的,setInterval 已正确存根,但它从未调用 setInerval()
  • 您是否尝试将刻度增加到更高的值,例如40000
  • 我做了..我尝试了几次。
  • 为什么getHumorEvery() 中需要async/await?我认为这就是原因。

标签: reactjs setinterval sinon


【解决方案1】:

调用 then on promises 并在异步函数中调用 await 将事件循环的代码排队,直到当前同步代码完成并且时钟滴答声才会执行。同样,setTimeout 通常会将代码添加到队列中,该队列也必须等到下一个时钟滴答。

Sinon fake timers“是 setTimeout 和朋友的同步实现”,“覆盖全局函数”并管理使用 setTimeout 和类似全局变量排队的代码,并在模拟时钟滴答时同步调用它。

仍在为事件循环排队的代码与之前为事件循环排队但现在被同步调用的代码之间的这种断开可能会导致问题(如thisthis)。

这些问题通常可以通过插入事件循环的手动循环来解决,以允许队列中的任何待处理代码在同步模拟时钟滴答之前执行。

在这种情况下,将测试转换为异步函数并在已解决的 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);
})

【讨论】:

  • 我会尝试用clock.tickAsync 替换clock.tick 并避免额外的await Promise.resolve();
猜你喜欢
  • 1970-01-01
  • 2021-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
  • 2011-11-07
  • 1970-01-01
相关资源
最近更新 更多