这几乎不是我第一次接触"1 timer(s) still in the queue"
时遇到的,但通常我会找到某种方法来使用tick()
或detectChanges()
等来摆脱它。
在我尝试测试我知道应该引发异常的条件之前,下面的测试工作正常:
it('should be able to change case', fakeAsync(() => {
expect(component).toBeTruthy();
fixture.whenStable().then(fakeAsync(() => {
component.case = 'lower';
fixture.autoDetectChanges();
tick(500);
const input = fixture.nativeElement.querySelector('input') as HTMLInputElement;
typeInElement('abcDEF', input);
fixture.autoDetectChanges();
tick(500);
expect(component.text).toEqual('abcdef');
component.case = 'upper';
fixture.autoDetectChanges();
tick(500);
typeInElement('abcDEF', input);
fixture.autoDetectChanges();
tick(500);
expect(component.text).toEqual('ABCDEF');
// Everything above works fine. Here's where the trouble begins
expect(() => {
component.case = 'foo';
fixture.autoDetectChanges();
tick(500);
}).toThrowError(/Invalid case attribute/);
}));
}));
我正在测试的是一个Angular组件,该组件是Material输入字段的包装。该组件具有许多可选属性,其中大多数只是通用输入字段功能的直通属性,但也有一些自定义属性,例如我上面测试的用于大写/小写转换的属性。
case
属性的可接受值为upper
,lower
和mixed
(带有空字符串,空值或未定义为mixed
的值) 。该组件应该为其他任何东西抛出异常。显然可以,并且测试成功,但是随着成功,我得到了:
ERROR: 'Unhandled Promise rejection:', '1 timer(s) still in the queue.', '; Zone:', 'ProxyZone', '; Task:', 'Promise.then', '; Value:', Error: 1 timer(s) still in the queue.
Error: 1 timer(s) still in the queue.
...
任何人都可以告诉我我可能做错了什么,或者是清除挥之不去的计时器的好方法吗?
免责声明:当我寻求有关Karma单元测试的最大问题是,即使我明确搜索“ karma”,我也大多会找到Pr0tractor,Pr0tractor以及更多Pr0tractor的答案。这不是Pr0tractor! (故意将零误拼写为零,因此它不会获得搜索匹配项。)
更新:我可以这样解决我的问题:
expect(() => {
component.inputComp.case = 'foo';
}).toThrowError(/Invalid camp-input case attribute/);
这不像通过测试组件模板中的HTML属性分配(错误)值那样好的测试,因为我只是将值直接强加到属性本身的组件设置器中,但是,直到我有更好的解决方案为止。
答案 0 :(得分:13)
我也遇到过类似的问题。解决方案是使用flush函数。
import { fakeAsync, flush } from '@angular/core/testing';
it('test something', fakeAsync(() => {
// ...
flush();
}));
答案 1 :(得分:11)
我最近遇到了同样的问题-为了解决我在discardPeriodicTasks()
函数结尾处从@angular/core/testing
叫it
的问题,此后我的测试通过了。
在这种情况下,您可能希望将其插入到最终expect
it('should be able to change case', fakeAsync(() => {
expect(component).toBeTruthy();
fixture.whenStable().then(fakeAsync(() => {
component.case = 'lower';
fixture.autoDetectChanges();
tick(500);
const input = fixture.nativeElement.querySelector('input') as HTMLInputElement;
typeInElement('abcDEF', input);
fixture.autoDetectChanges();
tick(500);
expect(component.text).toEqual('abcdef');
component.case = 'upper';
fixture.autoDetectChanges();
tick(500);
typeInElement('abcDEF', input);
fixture.autoDetectChanges();
tick(500);
expect(component.text).toEqual('ABCDEF');
discardPeriodicTasks() <-------------------- try here
// Everything above works fine. Here's where the trouble begins
expect(() => {
component.case = 'foo';
fixture.autoDetectChanges();
tick(500);
}).toThrowError(/Invalid case attribute/);
}));