【问题标题】:Understanding Sinon clock `tick` vs `tickAasync`了解 Sinon 时钟 `tick` 与 `tickAasync`
【发布时间】:2022-01-09 11:13:15
【问题描述】:

我试图了解clock.tickclock.tickAsync 之间的区别以及我应该在哪里使用它们。文档中的解释对我来说并不清楚,通过查看代码本身,我仍然无法理解我应该在何时何地使用每种方法。谁能帮我提供一个具体的代码示例?

【问题讨论】:

    标签: javascript jestjs sinon clock


    【解决方案1】:

    tickAsync() 也会中断事件循环,允许任何预定的 Promise 回调在运行计时器之前执行。

    首先,我建议查看video about event loop

    如果简短,ticktickAsync 之间的区别在于 tick - 是调用计时器 同步tickAsync 是 - 调用计时器 异步允许在调用计时器之前执行已解决的承诺

    同步意味着什么。让我们看一下我们要测试的示例代码

    function myFunction() {
      setTimeout(() => console.log('foo'), 1000)
      Promise.resolve().then(() => console.log('zoo'));
      console.log('bar')
    }
    

    还有我们的同步测试代码

    it('should test synchronously', () => {
       myFunction()
       tick(1000); // This would call scheduled timers synchronously ⚠️
       console.log('baz')
    });
    // print 'bar'
    // print 'foo'
    // print 'baz'
    // print 'zoo'
    

    现在让我们看看相同的测试代码,但使用tickAsync

    it('should test synchronously', () => {
       myFunction()
       tickAsync(1000);
       console.log('baz')
    });
    // print 'bar'
    // print 'baz' ?
    // print 'zoo' ?
    // print 'foo' ?
    

    如您所见,打印字符串的顺序发生了变化。 现在相同的代码,但 await

    it('should test synchronously', async () => {
       myFunction()
       await tickAsync(1000);
       console.log('baz')
    });
    // print 'bar'
    // print 'zoo' ?
    // print 'foo' ?
    // print 'baz' ?
    

    要了解顺序更改的原因,您应该了解micro tasks queue 和常规队列之间的区别。但是,如果您通过上面的链接观看了视频,您应该已经明白了?

    附: 此外,您应该了解sinon.useFakeTimers(); 将在自己的实现中替换setTimeoutsetInterval,从而允许 sinon 完全控制传递给这些函数的计时器

    这是一个非常粗略的近似是如何实现 sinon tick & tickAsync

    scheduledTimers = [];
    
    function useFakeTimers() {
        global.setInterval = global.setTimeout = (fn) => {
            scheduledTimers.push(fn);
        }
    }
    
    function tick() {
        while (scheduledTimers.length) {
            scheduledTimers.shift()();
        }
    }
    
    function tickAsync() {
        // Call timers on the next tick
        return Promise.resolve().then(() => tick());
    }
    

    【讨论】:

    • 所以可以肯定地说最常见和最安全的滴答方法是tickAsync?我猜大多数时候,当您在测试中提前时间时,您希望所有计时器(到那一点)在您继续您的下一个期望之前都已完成,对吧?
    • 视情况而定,我个人更喜欢在可能的情况下不处理异步测试。但是是的,tickAsync 的行为与现实世界非常接近,并允许处理诸如混合计时器和承诺之类的复杂情况
    猜你喜欢
    • 2014-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    相关资源
    最近更新 更多