Fake Async With Observable Subscription: 1 Timer仍在队列中



我正在为我的组件编写单元测试,该组件通过Observable链检索状态,并将其显示在UI中的状态徽章中。实现效果很好,但我遇到了使用jasminefakeAsync验证数据的问题

Component.ts:

@Component({
...
})
export class EmployerQuickactionsComponent {
private activeTag: Tag = { severity: 'success', text: 'Active'};
private inactiveTag: Tag = { severity: 'danger', text: 'Inactive'};
private selectedClinic$: Observable<Clinic> = this.modelService.selectedClinic$;
selectedEmployer$: Observable<Employer> = this.modelService.selectedEmployer$;
employerTag$: Observable<Tag> = combineLatest([this.selectedEmployer$, this.selectedClinic$]).pipe(
debounceTime(250),
mergeMap(([employer, clinic]) => {
if (!employer.id || !clinic.id) {
return of(null);
}
return this.clinicSiteEmployerService.get(employer.id, clinic.id).pipe(
map(clinicSiteEmployer => clinicSiteEmployer.isActive ? this.activeTag : this.inactiveTag)
);
})
);
constructor (<dependencies>) { }
} 

debounceTime操作符绕过了可以重新构建的竞争条件。但是这让我很好奇,是否有一种方法可以使用fakeAsync并在同一测试中订阅一个可观察对象。

这是我的component . specs .ts:

describe('EmployerQuickactionsComponent - Inactive Employer', () => {
beforeEach(() => {
...
});
it('should be initiated', fakeAsync(() => {
tick(250);
expect(fixture.componentInstance).toBeTruthy();
}));
it('should display tag if clinic selected', fakeAsync(() => {
tick(250);
expect(screen.getByLabelText('employer-action-tag')).toBeTruthy();
}));
it('should set inactive tag if employer is inactive', fakeAsync(done => {
tick(250);
fixture.componentInstance.employerTag$.subscribe((tag) => {
expect(tag.severity).toBe('danger');
expect(tag.text).toBe('Inactive');
done(); // throws error
});
}));

间谍程序都返回适当的模拟数据。我得到的错误是1 timer(s) still left in the queue.

任何帮助都将非常感激。

这个问题是由于Observable在fakeAsyn区域等待引起的,为了避免这个问题,你可以使用flush()来避免这种情况。
示例-
ts -

export class NetworkService {
constructor(private toastsService: ToastsService) {}

public async refreshData(): Promise<void> {
await Promise.resolve(); // fake network call
this.toastsService.addToast("Data refreshed.");
}
}         

规范。ts -

it("should add a toast", fakeAsync(() => {
const toastsService = TestBed.inject(ToastsService);
const toasts = toastsService.getToasts();

service.refreshData();

flushMicrotasks();

// the following assertions will pass
expect(toasts.length).toBe(1);
expect(toasts[0].message).toBe("Data refreshed.");

// without flush at the end, the test will fail with
// Error: 1 timer(s) still in the queue.
flush();
}));         

https://github.com/angular/angular/blob/master/packages/core/test/fake_async_spec.ts L273

最新更新