我试图在我的组件中对基于模板的表单进行单元测试。表单很简单,包含一个人的联系信息。我试图做的是对各种验证方案进行单元测试。我认为我能做的只是设置一个值,比如电子邮件地址,然后检查ngForm对象,获取相应的formControl for emailAddress,然后检查有效性状态。但是,我发现的是,表单虽然存在,但根本不包含任何控件。因此看起来形式永远不会完全构建。
代码(为了简洁起见,我省略了导入和一些提供者声明等):
人-细节接触-info.component.html
<custom-input type="text"
name="emailAddress"
[(ngModel)]="model.emailAddress"
maxlength="255"
pattern="^[^\s@]+@[^\s@]+\.[^\s@]{2,}$"
#emailAddress="ngModel">
</custom-input>
<custom-input type="text"
[disabled]="permissions.canViewOnly"
name="phone"
[(ngModel)]="model.phone"
maxlength="16">
</custom-input>
<custom-input type="text"
[disabled]="permissions.canViewOnly"
name="model.fax"
[(ngModel)]="fax"
maxlength="16">
</custom-input>
人-细节接触-info.component.ts
@Component({
selector: 'person-details-contact-info',
templateUrl: 'person-details-contact-info.component.html',
viewProviders: [{ provide: ControlContainer, useExisting: NgForm }]
})
export class PersonDetailsContactInfoComponent {
@Input('model')
model: {
emailAddress: '',
phone: '',
fax: ''
}
}
**单位测试代码**
@Component({
template: `
<form #form="ngForm">
<person-details-contact-info [(model)]="model">
</person-details-contact-info>
</form>
`,
providers: [ ]
})
export class TestHostComponent {
model: PersonDetailsContactInfoModel = new PersonDetailsContactInfoModel();
@ViewChild('form')
ngForm: NgForm;
}
describe('In the file "person-details-contact-info.component.ts', () => {
let fixture: ComponentFixture<TestHostComponent>;
let component: TestHostComponent;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [FormsModule, NoopAnimationsModule],
declarations: [TestHostComponent, PersonDetailsContactInfoComponent],
providers: [ ]
});
fixture = TestBed.createComponent(TestHostComponent);
component = fixture.componentInstance;
});
it('is has invalid email format', () => {
component.model.emailAddress = 'an invalid email format.';
fixture.detectChanges();
const ctrl = component.ngForm.form.get('emailAddress');
expect(ctrl.valid).toBe(false);
});
});
以上测试是错误的,因为&#34; ctrl&#34; object为null。表单中不存在emailAddress控件。顺便说一句,这一切在实际组件中都能很好地工作,所以很明显我在单元测试设置上做错了。
最后,为了理解代码,我的应用程序的方式是将一个非常大的表单分解为单独的组件。所以这&#34;联系信息&#34; component是一个更大的形式的一部分。这就是为什么我绑定到模型并在person-details-contact-info.component的providers部分中提供现有的NgForm。同样,一切都在应用程序本身内完美运行,它只是我尝试进行单元测试的方式并没有按照我的预期进行。
答案 0 :(得分:3)
好的,我知道发生了什么。我正在尝试做的但是在单元测试的“it”块内,在“fixture.detectChanges()”之后,我需要做一个“fixture.whenStable()”。例如:
it('is has invalid email format', () => {
component.model.emailAddress = 'an invalid email format.';
fixture.detectChanges();
fixture.whenStable().then(() => {
const ctrl = component.ngForm.form.get('emailAddress');
expect(ctrl.valid).toBe(false);
});
});
这很有趣,因为我在实际的应用程序中遇到了类似的问题,其中一个组件显然不是“稳定”的。尝试在表单中立即访问(在OnInit或AfterViewInit内)formControls将导致null对象。