【发布时间】:2022-01-09 11:13:15
【问题描述】:
我试图了解clock.tick 和clock.tickAsync 之间的区别以及我应该在哪里使用它们。文档中的解释对我来说并不清楚,通过查看代码本身,我仍然无法理解我应该在何时何地使用每种方法。谁能帮我提供一个具体的代码示例?
【问题讨论】:
标签: javascript jestjs sinon clock
我试图了解clock.tick 和clock.tickAsync 之间的区别以及我应该在哪里使用它们。文档中的解释对我来说并不清楚,通过查看代码本身,我仍然无法理解我应该在何时何地使用每种方法。谁能帮我提供一个具体的代码示例?
【问题讨论】:
标签: javascript jestjs sinon clock
tickAsync() 也会中断事件循环,允许任何预定的 Promise 回调在运行计时器之前执行。
首先,我建议查看video about event loop。
如果简短,tick 和 tickAsync 之间的区别在于 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(); 将在自己的实现中替换setTimeout 和setInterval,从而允许 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?我猜大多数时候,当您在测试中提前时间时,您希望所有计时器(到那一点)在您继续您的下一个期望之前都已完成,对吧?