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

nip*_*777 17 javascript unit-testing asynchronous jasmine angular

我试图从Angular 2中的模拟后端获得单元测试的结果.目前,我们使用fakeAsync超时来模拟时间的流逝.

目前的工作单位测试

it('timeout (fakeAsync/tick)', fakeAsync(() => {
    counter.getTimeout();
    tick(3000); //manually specify the waiting time
}));
Run Code Online (Sandbox Code Playgroud)

但是,这意味着我们仅限于手动定义的超时.不是在异步任务完成时.我要做的是tick()等待任务完成后再继续测试.

这似乎没有按预期工作.

阅读fakeAsynctick答案在这里解释说:

tick()模拟异步时间的流逝.

我设置了一个模拟这个场景的plnkr示例.

在这里,我们调用getTimeout()调用具有超时的内部异步任务的方法.在测试中,我们尝试包装它并tick()在调用getTimeout()方法后调用.

counter.ts

getTimeout() {
  setTimeout(() => {
    console.log('timeout')
  },3000)
}
Run Code Online (Sandbox Code Playgroud)

counter.specs.ts

it('timeout (fakeAsync/tick)', fakeAsync(() => {
    counter.getTimeout();
    tick();
}));
Run Code Online (Sandbox Code Playgroud)

但是,单元测试失败,错误"错误:1个计时器仍在队列中".

角度回购中问题是否与此有关?

是否可以使用tick()这种方式等待超时功能?或者我可以使用另一种方法吗?

小智 21

尝试将以下函数调用的一个或组合添加到测试的末尾:

    flush();
    flushMicrotasks();
    discardPeriodicTasks();
Run Code Online (Sandbox Code Playgroud)
  1. flush(带有可选的 maxTurns 参数)也会刷新宏任务。(Angular 测试教程中没有提到这个功能。)
  2. flushMicrotasks 刷新微任务队列。
  3. discardPeriodicTasks 取消“仍在队列中的周期计时器”。

队列中的计时器并不一定意味着您的代码存在问题。例如,观察当前时间的组件可能会引入这样的计时器。如果您使用来自外部库的此类组件,您可能还会考虑存根它们而不是“追逐计时器”。

如需进一步了解,你可以看看的JavaScript代码fakeAsync的功能zone-testing.js


nep*_*hiw 14

的目的fakeAsync是在您的规范内控制时间。tick它将不会等待任何时间,因为它是用于模拟时间流逝的同步功能。如果您要等到异步功能完成,则需要使用asyncwhenStable,但是,在您的示例中,规范将需要3秒钟才能通过,因此我不建议这样做。

为什么原因counter.spec.ts失败是你唯一的模拟0秒(通常用于表示该事件循环的下一个刻度)的通道。因此,当规范完成时,仍然有模拟计时器处于活动状态,这会使整个规范失效。通知您模拟了超时,并且未处理,它实际上在正常工作。

基本上,我认为你正试图利用fakeAsynctick为他们并不打算使用方式。如果您需要按照建议的方法测试超时,最简单的方法就是setTimeout自己模拟函数,以便无论使用什么时间,都可以调用该方法。

编辑 我遇到一个相关的问题,我想清除计时器,由于它不是受测试的部件,所以我不在乎它花了多长时间。我试过了:

tick(Infinity);
Run Code Online (Sandbox Code Playgroud)

哪个可行,但超级hacky。我最终去了

discardPeriodicTasks();
Run Code Online (Sandbox Code Playgroud)

而且我所有的计时器都清除了。

  • 尝试了一切,但“discardPeriodicTasks()”工作完美 (7认同)

dan*_*hao 7

在每个测试的末尾添加:

 fixture.destroy();
 flush();
Run Code Online (Sandbox Code Playgroud)

  • 它将等待任务从 3 变为 1。但仍有一个在队列中。 (2认同)

Nic*_*ick 0

我通常在单元测试中使用lushMicrotasks 方法来与我的服务一起使用。我读过,tick() 与flushMicrotasks 非常相似,但也调用jasmine tick() 方法。