最近我已经阅读了很多有关角度测试的信息,并且它们始终是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/Tick
和fixture.detectChanges
之间的区别。我的问题是,在fixture.whenstable
执行区中,FakeAsync
会作为Async
区域执行什么操作,以便跟踪fixture.whenstable
的异步工作,至少据我了解。甚至如果确实使用了它,也完全不在异步执行区内的话。
因此,如果在FakeAsync函数内部使用了fix.whenstable,或者未设置异步执行区域的函数,它将按预期工作吗?
答案 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();
})
);