角度测试中的 tick() 和 flush() 有啥区别?

Posted

技术标签:

【中文标题】角度测试中的 tick() 和 flush() 有啥区别?【英文标题】:What is the difference between tick() and flush() in angular testing?角度测试中的 tick() 和 flush() 有什么区别? 【发布时间】:2019-10-23 05:24:43 【问题描述】:

在 Angular 文档中,我看到了这两个函数,tick()flush()。这两个似乎都做类似的事情。从角度文档中,它说:

模拟 fakeAsync 区域中计时器的异步时间流逝。

对于冲洗:

通过排空宏任务队列直到它为空,模拟 fakeAsync 区域中的计时器的异步时间流逝。返回值是已经过去的毫秒数。

谁能给我解释一下区别?

编辑(在 cmets 中回答):

另外,angular documentation中tick()是不带参数使用的,该行的注释甚至使用了短语“flush”

it('should display error when TwainService fails', fakeAsync(() => 
  // tell spy to return an error observable
  getQuoteSpy.and.returnValue(
    throwError('TwainService test failure'));

  fixture.detectChanges(); // onInit()
  // sync spy errors immediately after init

  tick(); // flush the component's setTimeout()

  fixture.detectChanges(); // update errorMessage within setTimeout()

  expect(errorMessage()).toMatch(/test failure/, 'should display error');
  expect(quoteEl.textContent).toBe('...', 'should show placeholder');
));

【问题讨论】:

【参考方案1】:

相对于之前启动的异步操作,它们做了不同的事情。例如;调用 setTimeout(...) 会启动异步操作。

tick()时间向前移动。 flush()时间移到末尾。

这些功能的单元测试可以更好地说明这一点。

打勾

此单元测试显示,在所有 10 个计时器完成之前,tick 被用于以 steps 的方式将时间向前移动。 Tick 被多次调用。

https://github.com/angular/angular/blob/master/packages/core/test/fake_async_spec.ts#L205


      it('should clear periodic timers', fakeAsync(() => 
           let cycles = 0;
           const id = setInterval(() =>  cycles++; , 10);

           tick(10);
           expect(cycles).toEqual(1);

           discardPeriodicTasks();

           // Tick once to clear out the timer which already started.
           tick(10);
           expect(cycles).toEqual(2);

           tick(10);
           // Nothing should change
           expect(cycles).toEqual(2);
         ));

冲洗

这个单元测试表明所有异步任务在返回时都应该完成,并且返回的值告诉你完成它们需要多长时间。

https://github.com/angular/angular/blob/master/packages/core/test/fake_async_spec.ts#L273

      it('should flush multiple tasks', fakeAsync(() => 
           let ran = false;
           let ran2 = false;
           setTimeout(() =>  ran = true; , 10);
           setTimeout(() =>  ran2 = true; , 30);

           let elapsed = flush();

           expect(ran).toEqual(true);
           expect(ran2).toEqual(true);
           expect(elapsed).toEqual(30);
         ));

【讨论】:

这是有道理的,但从angular documentation 来看,使用不带任何参数的tick() 似乎可以有效地进行刷新。 @JustinKavalan 是的,我也读过。因此,基本上没有参数意味着tick()all 向前移动。所以它与flush() 相同。不同之处在于tick() 不返回经过的时间。 @JustinKavalan 如果这回答了您的问题。请接受它作为答案。 我只是想补充一点,tick()flush() 不相等。我有一个测试,我在单击触发的订阅中监视router.navigate,并使用tick() 在队列中留下一个定期计时器,而flush() 没有。 (有趣的是flush() 在这个测试中总是返回 500 毫秒。) 我认为没有参数的tick() 只是运行即时计时器,例如setTimeout(() => doSomething(), 0)flush() 基本上就是while(testZone.hasPendingTasks) tick(1);

以上是关于角度测试中的 tick() 和 flush() 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

HDU1006 Tick and Tick

angular2 测试中 fakeAsync 的 tick() 和 done() 有啥区别?

python使用matplotlib可视化自定义Y轴轴标签刻度旋转的角度(customize degree rotating axis tick labels in matplotlib)

Angular 2 fakeAsync 在使用tick()的函数中等待超时?

杭电ACM HDU 1006 Tick and Tick

深入理解 Lucene 的 flush 过程