我组件的视图必须显示一些从组件数据生成的复选框(并有条件地检查并由[(NgModel)]绑定)。
<div *ngFor="let checkableColumn of visibleCatalog">
<label nz-checkbox [(ngModel)]="checkableColumn.checked">
{{ checkableColumn.column.label | titlecase }}
</label>
</div>
我了解NgModel更新是异步的,因此我将测试放在了一个falseAsnyc上下文中,以简化测试。
我的第一次尝试是:
it('should update his checkboxes', fakeAsync(() => {
component.ngOnChanges({}); // For populating my data
fixture.detectChanges();
tick();
const checkboxesChecked = document.querySelectorAll('input[type=checkbox]:checked');
expect(checkboxesChecked.length).withContext('1 checkbox should be checked').toBe(1);
}));
但是它不起作用,没有选中任何复选框,我发现以下内容可以实现:
it('should update his checkboxes', fakeAsync(() => {
component.ngOnChanges({}); // For populating my data
fixture.detectChanges(); // Added
tick();
fixture.detectChanges();
const checkboxesChecked = document.querySelectorAll('input[type=checkbox]:checked');
expect(checkboxesChecked.length).withContext('1 checkbox should be checked').toBe(1);
}));
我不明白为什么我需要在tick()之前更新视图。 有谁了解这种行为?
答案 0 :(得分:1)
这个非常棘手的问题。
从angular documentation on testing看来,第一个 detectChanges 仅通过onInit()。为了查看您的异步更改,您需要经过滴答并再次运行,因为尚未开始更新异步过程(仅在初始化组件后才开始)。
it('should display error when TwainService fails', fakeAsync(() => {
// tell spy to return an error observable
getQuoteSpy.and.returnValue(
throwError('TwainService test failure'));
fixture.detectChanges(); // onInit()
// sync spy errors immediately after init
tick(); // flush the component's setTimeout()
fixture.detectChanges(); // update errorMessage within setTimeout()
expect(errorMessage()).toMatch(/test failure/, 'should display error');
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
}));
对于同步情况,角状态如下:
由于间谍结果同步返回,因此getQuote()方法 第一次更改后立即更新屏幕上的消息 Angular调用ngOnInit的检测周期。
测试错误路径时,您不是很幸运。虽然服务 间谍将同步返回错误,组件方法调用 setTimeout()。测试必须等待至少一整圈 该值可用之前的JavaScript引擎。测试必须 变得异步。