Angular - 强制反应形式在单元测试中有效

Angular - Forcing a reactive form to be valid in a unit test

我正在使用 Angular v4.4.4。在组件中,单击模板中的按钮后,假设反应式表单有效,表单将被保存。类似于(伪代码):

public onSave(): void {
    if (this.myForm.valid) {
        this._createFoo();
    }
}

private _createFoo(): void {
    this._fooService.createItem(this.foo).subscribe(result => {
        // stuff happens...
    });
}

在相关的单元测试中,我需要强制表单有效,以便确认正在调用服务。像这样:

it('should create Foo', () => {
    const spy = spyOn(_fooService, 'createItem').and.callThrough();
    component.foo = new Foo();
    fixture.detectChanges();
    const bookButton = fixture.debugElement.query(By.css('#bookButton'));
    expect(bookButton !== null).toBeTruthy('missing Book button');
    bookButton.triggerEventHandler('click', null);
    expect(spy).toHaveBeenCalled();
});

这将失败,因为 myForm 从未设置为有效。

在这种特殊情况下,我不想为表单中的每个输入都赋值。我只需要观察并查看服务订阅是否发生。如何强制表单有效?

为什么不直接清除验证者列表?

// If there are any async validators
//
this.myForm.clearAsyncValidators();
// If there are any normal validators
//
this.myForm.clearValidators();
// Doing the validation on all the controls to put them back to valid
//
this.formGroup.updateValueAndValidity();

这将确保您的表单没有验证器,因此是有效的。

如果有人还在为此苦苦挣扎:

正如@realappie 回答所暗示的,我们应该清除所有 sync/async 个验证器。 但在大多数情况下,验证器位于控件上,而不是表单本身。所以,只需循环所有控件,对每个控件执行此操作。

从测试文件看应该是这样的:

const controls = component.myForm.controls;

for (const control in controls) {
    // Clear sync validators - use clearAsyncValidators() for async
    // validators
    controls[control].clearValidators();
    // should update just the control and not everything
    controls[control].updateValueAndValidity({ onlySelf: true });
}
component.myForm.updateValueAndValidity();

仅使用 javascript,您可以:

      Object.defineProperty(comp.editForm, 'valid', {
        get: () => true
      });

覆盖 getter,始终 return 为真。