就错误而言。看来您只需要导入By。这不是全球性的。它应该从以下模块导入
import { By } from '@angular/platform-browser';
就测试部分而言,这是我能够弄清楚的。当您更改组件中的值时,您需要触发更改检测以更新视图。您可以使用fixture.detectChanges() 执行此操作。完成此操作后,通常应该使用该值更新视图。
从测试类似于您的示例的内容来看,情况似乎并非如此。在更改检测之后似乎仍然有一些异步任务正在进行。假设我们有以下
const comp = fixture.componentInstance;
const select = fixture.debugElement.query(By.css('select'));
comp.selectedValue = 'a value';
fixture.DetectChanges();
expect(select.nativeElement.value).toEqual('1: a value');
这似乎不起作用。似乎有一些异步正在进行,导致尚未设置该值。所以我们需要通过调用fixture.whenStable来等待异步任务
comp.selectedValue = 'a value';
fixture.DetectChanges();
fixture.whenStable().then(() => {
expect(select.nativeElement.value).toEqual('1: a value');
});
以上方法可行。但是现在我们需要触发 change 事件,因为这不会自动发生。
fixture.whenStable().then(() => {
expect(select.nativeElement.value).toEqual('1: a value');
dispatchEvent(select.nativeElement, 'change');
fixture.detectChanges();
fixture.whenStable().then(() => {
// component expectations here
});
});
现在我们有另一个来自事件的异步任务。所以我们需要再次稳定它
以下是我测试过的完整测试。这是source code integration tests 中示例的重构。他们使用了fakeAsync 和tick,这类似于使用async 和whenStable。但是对于fakeAsync,你不能使用templateUrl,所以我认为最好将它重构为使用async。
源代码测试也是一种双单向测试,首先测试模型以查看,然后查看模型。虽然看起来你的测试试图做一种双向测试,从模型到模型。因此,我对其进行了一些重构,以更好地适应您的示例。
import { Component } from '@angular/core';
import { TestBed, getTestBed, async } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { dispatchEvent } from '@angular/platform-browser/testing/browser_util';
@Component({
selector: 'ng-model-select-form',
template: `
<select [(ngModel)]="selectedCity" (ngModelChange)="onSelected($event)">
<option *ngFor="let c of cities" [ngValue]="c"> {{c.name}} </option>
</select>
`
})
class NgModelSelectForm {
selectedCity: {[k: string]: string} = {};
cities: any[] = [];
onSelected(value) {
}
}
describe('component: NgModelSelectForm', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ FormsModule ],
declarations: [ NgModelSelectForm ]
});
});
it('should go from model to change event', async(() => {
const fixture = TestBed.createComponent(NgModelSelectForm);
const comp = fixture.componentInstance;
spyOn(comp, 'onSelected');
comp.cities = [{'name': 'SF'}, {'name': 'NYC'}, {'name': 'Buffalo'}];
comp.selectedCity = comp.cities[1];
fixture.detectChanges();
const select = fixture.debugElement.query(By.css('select'));
fixture.whenStable().then(() => {
dispatchEvent(select.nativeElement, 'change');
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(comp.onSelected).toHaveBeenCalledWith({name : 'NYC'});
console.log('after expect NYC');
});
});
}));
});