如果不在异步测试执行区中,fixture.whenStable()在我的角度测试中是否真的做了什么?

时间:2018-11-26 11:19:58

标签: angular unit-testing

最近我已经阅读了很多有关角度测试的信息,并且它们始终是async + fixture.whenStable和fakeAsync + tick,但是您可以随时调用fixtrue.whenStable,因为它并不是紧密耦合的。如果您在不使用async实用程序在测试区域中跟踪Promise时调用它,它实际上会做什么?

例如:

it('should be able to do this thing that needs some async setup', () => {
            fixture.detectChanges();
            fixture.whenStable().then()
});

我了解FakeAsync/Tickfixture.detectChanges之间的区别。我的问题是,在fixture.whenstable执行区中,FakeAsync会作为Async区域执行什么操作,以便跟踪fixture.whenstable的异步工作,至少据我了解。甚至如果确实使用了它,也完全不在异步执行区内的话。

因此,如果在FakeAsync函数内部使用了fix.whenstable,或者未设置异步执行区域的函数,它将按预期工作吗?

3 个答案:

答案 0 :(得分:2)

如果您在whenStable()中没有async的情况下进行测试,则fakeAsync不会执行任何操作。 whenStable()的工作是等待测试NgZone中的所有任务完成。如果您不进行异步测试,则根本不会创建NgZone,而whenStable()会立即返回。

如果需要更多详细信息,请检查GitHub中ComponentFixture的代码。

答案 1 :(得分:2)

接受的答案在编写时可能是正确的,但是截至2020年末,使用node_modules/zone.js/bundles/zone-testing.umd.js时,我认为它不再适用了。我在文档中找不到引用,但可以通过实验确认始终使用测试区,并且whenStable等待其任务完成。

这很容易尝试。只需创建一个空测试,然后添加

//// In my.component.ts
import { timer } from "rxjs";
import { map } from "rxjs/operators";

@Component({
  template: `<p>{{clock|async}}</p>,
  ...
})
export class MyComponent {
  /** @internal */ public readonly clock = timer(0,1000).pipe(map(() => new Date()));
}


//// In `my.component.spec.ts`
beforeEach(async () => {
    testBed.configureTestingModule(...);
    await testBed.compileComponents();
    fixture = testBed.createComponent(MyComponent);
    await fixture.whenStable();
});

由于rxjs timer在后​​台使用setInterval,因此被标记为始终有待处理的任务,因此whenStable永远不会解决。茉莉花将失败,并超时,等待setup方法返回的Promise解析。 (问我我是怎么发现的...)

答案 2 :(得分:0)

尝试将您的测试代码包装到 waitForAsync

这是在 angular 中测试异步代码的新推荐方法

  @Component()
  export class SomeComponent implements OnInit {
    async ngOnInit() {
      // to test component with async ngOnInit use waitForAsync
    }
  }

  beforeEach(
    waitForAsync(() => {
      fixture = TestBed.createComponent(SomeComponent);
      component = fixture.componentInstance;
      fixture.detectChanges();
    })
  );