我知道tick()函数利用fakeAsync。而且我也可以同时使用fixture.whenStable().then()asyncfakeAsync

我想知道两者的确切用例。谁能举例说明。

注意:我想在两种情况下都使用Fake Service或Stub。

最佳答案

tl; dr
在几乎所有情况下,它们都可以互换使用,但是除非需要进行XHR调用,否则首选使用fakeAsync()/tick()组合,在这种情况下,您必须使用async()/whenStable()组合,因为fakeAsync()不支持XHR调用。

在大多数情况下,它们可以互换使用。除了组件的外部模板和样式未内联编译到要测试的组件中(即使用SystemJS)的情况下,我想不出什么就需要其他组件。使用SystemJS时,会对外部模板和样式进行XHR调用。进行XHR调用时,不能使用fakeAsync()。另一方面,当使用Webpack时,外部模板和样式将内联编译,因此可以使用fakeAsync()
除此之外,我认为这是样式偏爱的问题。我可以说的一件事是,假设您需要进行多个异步调用,例如this example。您需要嵌套的fixture.whenStable()调用,当它们变得如此深时,它们看起来可能很难看。

someAsyncAction();
fixture.whenStable().then(() => {
  fixture.detectChanges();
  expect(something)

  changeSomethingElseAsynchronously();
  fixture.whenStable().then(() => {
    fixture.detectChanges();
    expect(something);

    anotherAsyncAction();
    fixture.whenStable().then(() => {
      fixture.detectChanges()
      expect(somthingeElse)
    })
  })
})
如果没有所有的fixture.whenStable()和看起来同步的代码,这看起来可能会更干净(并且更易于推理)。
tick();
fixture.detectChanges();
expect(something)

changeSomethingAsynchronously()
tick();
fixture.detectChanges();
expect(somethingElse)

changeSomethingAsynchronously()
tick();
fixture.detectChanges();
expect(somethingElse);
我可能要添加的另一件事是我的OCD部分,始终需要检查是否调用了fixture.whenStable()中的调用
fixture.whenStable().then(() => {
  expect(...)
  console.log('called...')
})
假设您忘记将测试包装在async中。否则,测试将在fixture.whenStable解析之前完成,您将永远不会知道。看起来好像测试通过了,这是一个误报。实际发生的是断言从未被调用过。
因此,我实际上已经远离async了。但是,如果您喜欢这种样式,并相信自己始终将测试包装在async中,请坚持使用它。但是,使用fakeAsync,所有内容都被同步调用,因此没有断言不会被调用的机会。

09-26 13:15