我了解async
和fakeAsync
方法会设置某种侦听器,该侦听器记录所有异步操作,以便角度测试框架可以使用whenStable
和tick()
进行管理等待所有这些东西完成。我认为那是正确的吗?
我要努力理解的是,实际上是否存在执行顺序上的差异-因为如果没有,为什么要同时提供两者?
这使我学习了JS宏任务和Micro任务,我想知道这两种方法是否在这一领域有所不同?
答案 0 :(得分:5)
这是 Testing Asynchronous Code - CodeCraft
的摘要async
+ whenStable
:考虑以下这段代码:
it('Button label via async() and whenStable()', async(() => {
fixture.detectChanges();
expect(el.nativeElement.textContent.trim()).toBe('Login');
spyOn(authService, 'isAuthenticated').and.returnValue(Promise.resolve(true));
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(el.nativeElement.textContent.trim()).toBe('Logout');
});
component.ngOnInit();
}));
async
函数在特殊的 async
测试区域中执行其体内的代码。这样可以拦截并跟踪其体内创建的所有承诺。
仅当所有这些未完成的承诺都得到解决后,它才会解析从whenStable
返回的承诺。
您可以使用它来避免使用Jasmine的间谍机制来检测何时解决了诺言。
此机制比使用普通的Jasmine解决方案略胜一筹,但是还有另一个版本可以为我们提供细粒度的控制,还可以让我们将测试代码布置为同步的。
fakeAsync
+ tick
:现在考虑这段代码:
it('Button label via fakeAsync() and tick()', fakeAsync(() => {
expect(el.nativeElement.textContent.trim()).toBe('');
fixture.detectChanges();
expect(el.nativeElement.textContent.trim()).toBe('Login');
spyOn(authService, 'isAuthenticated').and.returnValue(Promise.resolve(true));
component.ngOnInit();
tick();
fixture.detectChanges();
expect(el.nativeElement.textContent.trim()).toBe('Logout');
}));
与async
一样,fakeAsync
函数在特殊的 伪造 async
测试区域中执行其体内的代码。这样可以拦截并跟踪其体内创建的所有承诺。
tick()
函数阻止执行并模拟时间的流逝,直到所有未完成的异步活动完成。
因此,当我们调用tick()
时,应用程序将坐下并等待承诺被解决,然后让执行移至下一行。
使用此方法的主要优点是,它使代码更加线性,就像我们正在执行同步代码一样,没有回调方法使思维混乱,并且所有内容都更易于理解。
我们可以使用三种机制来测试异步代码:
茉莉花的done
函数和间谍回调。这行得通,但希望我们了解应用程序中的所有承诺,并能够将它们挂钩。
我们可以使用Angular async
和whenStable
函数,我们不需要自己跟踪promise,但是我们仍然需要通过回调函数布置代码,这可能很难阅读。
我们可以使用Angular fakeAsync
和tick
函数,这还使我们可以将async
测试代码布置为同步的。
这些要点使您认为,如果难以阅读,为什么要使用async
+ whenStable
。为什么不简单地使用fakeAsync
+ tick
呢?嗯,原因之一可能是因为:
重要
fakeAsync
确实有一些缺点,例如doesn’t track XHR requests。
您可以在此GitHub Thread上了解有关此内容的更多信息。