为什么我的Angular测试不像我的自定义表单验证功能?

时间:2018-02-01 02:49:14

标签: javascript angular typescript jasmine karma-runner

我有一个角度组件 - " FooComponent" - 我试图使用Karma / Jasmine进行测试。

以下是foo.component.spec.ts文件中的一些相关代码:

describe('FooComponent', () => {
    let component: FooComponent
    let fixture: ComponentFixture<FooComponent>
    let componentElement: DebugElement
    let bar: FormControl

...

beforeEach(() => {
    fixture = TestBed.createComponent(FooComponent)
    component = fixture.componentInstance
    fixture.detectChanges()
    component.ngOnInit()
    componentElement = fixture.debugElement
    bar = component.bar
  })

it('should create the FooComponent', () => {
    expect(component).toBeTruthy()
})

运行ng test时出现以下错误:

Chrome 63.0.3239 (Windows 10 0.0.0) FooComponent should create the 
FooComponent FAILED

    TypeError: Cannot read property 'validate' of undefined
        at normalizeValidator .../node_modules/@angular/forms/esm5/forms.js:1059:23)
        at Array.map (<anonymous>)
        at composeValidators .../node_modules/@angular/forms/esm5/forms.js:2422:1)
        at coerceToValidator .../node_modules/@angular/forms/esm5/forms.js:2826:1)
        at new FormControl .../node_modules/@angular/forms/esm5/forms.js:3881:1)
        at FooComponent.webpackJsonp.../../../../../src/app/foo/foo.component.ts.FooComponent.createFormControls ....../src/app/foo/foo.component.ts:43:16)
        at FooComponent.webpackJsonp.../../../../../src/app/foo/foo.component.ts.FooComponent.ngOnInit ....../src/app/foo/foo.component.ts:37:10)
        at checkAndUpdateDirectiveInline .../node_modules/@angular/core/esm5/core.js:12400:1)
        at checkAndUpdateNodeInline .../node_modules/@angular/core/esm5/core.js:13927:1)
        at checkAndUpdateNode .../node_modules/@angular/core/esm5/core.js:13870:1)

如您所见,foo.component.ts的第37行和第43行令人反感:

ngOnInit() {
    //the following is line 37
    this.createFormControls()
    this.createForm()
}

createFormControls() {
    //the following is line 43
    this.bar = new FormControl('', [Validators.required, this.fooService.validateBar])
}

createForm() {
    this.fooForm = new FormGroup({
        bar: this.bar
    })
}

所以看起来它不喜欢我在FooService中编写的自定义验证函数(我将其注入FooComponent)。这是foo.service.ts中的那个函数:

validateBar(bar: FormControl) {
    return bar.value.length == 10 ? null: { invalidBar: true }
}

有什么想法吗?

2 个答案:

答案 0 :(得分:0)

我看到你在beforeEach

中有这个
beforeEach(() => {
    ...
    component.ngOnInit()
    ...
});

您不应该直接调用ngOnInit(),当您执行此操作时,测试运行程序会调用该方法:

fixture.detectChanges()

您可以参考解释此问题的文档:https://angular.io/guide/testing

答案 1 :(得分:0)

如果有人偶然发现了这一点,“cannot read property 'validate' of undefined”错误可能是最烦人的事情,而且几乎没有答案描述要尝试的内容。

问题是您的 formGroup 未定义,但您的 HTML 正在尝试呈现并检查 formGroup.valid(例如您的表单提交按钮是否已启用)

通常模拟 FormBuilder(),FormGroup,构建可重用组件所需的数据对象,然后将其提供给组件就足够了,一切都很好。但有些时候不是

无论如何.. 尝试添加一个 ngIf 以便在允许呈现组件之前初始化控件

<form class="form-popup" *ngIf="formGroup && formGroup.controls.length" [formGroup]="formGroup">

这通常只有在组件使用可重用组件(用于外观),然后在 ngOnInit 上注入 formGroup 数据时才会出现问题。哇啦啦——

<ng-template *ngComponentOutlet="component;injector:injector"></ng-template

还没有足够的数据,且fixture.detectChanges() 不足以渲染它。