为什么ngForm“控件”属性在我的测试中是空的? (角)

为什么ngForm“控件”属性在我的测试中是空的? (角)

问题描述:

我有采用模板驱动的形式为什么ngForm“控件”属性在我的测试中是空的? (角)

<form (ngSubmit)="onSearchCorpus(form)" #form="ngForm"> 
<combo-box [(ngModel)]="model.corpus" name="corpus" #corpus="ngModel"></combo-box> 
<input [(ngModel)]="model.label" name="label" id="label" type="text" required pattern="^(?!\s*$)[\w\_\-\:\s]*" maxlength="50" class="form-control label-name" autocomplete="off" #label="ngModel"> 
<textarea [(ngModel)]="model.query" name="query" id="query" maxlength="3600" required validateQuerySyntax class="form-control search-query" #query="ngModel" #queryControl 
     placeholder="Example: (&quot;grantee&quot; OR &quot;grant&quot; OR &quot;sponsor&quot; OR &quot;contribute&quot; OR &quot;contributor&quot;) NEAR (&quot;non-profit organization&quot; OR &quot;charities&quot;)"> 
     </textarea> 
<button [disabled]="corpusValidationInProgress" type="submit" class="button-level-one">Search</button> 
</form> 

在处理表单提交的方法我访问NgForm实例controls性的成分,它在浏览器中正常工作。

onSearchCorpus(formData: NgForm) { 
    ... 
    const corpusErrors = formData.controls.corpus.errors; 
    ... 
} 

然而,当我尝试用噶测试这种方法的NgForm的controls属性为空。我很困惑这是为什么。该方法失败,错误cannot read property "errors" of undefined

这里是我的测试看起来像:

it('should not perform corpusSearch if selected corpus no longer exists',() => { 
    component.ngOnInit(); 
    const form = fixture.debugElement.query(By.css('form')); 
    form.triggerEventHandler('submit', null); 
    ... 
}); 

,这是我怎么设置我的测试套装:

beforeEach(async(() => { 
    TestBed.configureTestingModule({ 
     // schemas: [NO_ERRORS_SCHEMA], 
     imports: [ 
      FormsModule, 
      PopoverModule 
     ], 
     providers: [ 
      CorpusSearchService, 
      { provide: ApiService, useValue: ApiServiceStub }, 
      { provide: Router, useClass: RouterStab }, 
     ], 
     declarations: [ 
      SearchCorpusComponent, //<--component under test 
      ComboBoxComponent //<-- 3rd party combobox which is used for first control 
     ] 
    }).compileComponents(); 
})); 

beforeEach(() => { 
    fixture = TestBed.createComponent(SearchCorpusComponent); 
    component = fixture.componentInstance; 
    apiService = fixture.debugElement.injector.get(ApiService); 
    subject = new Subject(); 
}); 

那么,为什么controls处于测试环境是空的?

controls在测试环境中为“空”的原因是在调用onSearchCorpus时,控件在测试环境中尚未初始化。

我准备了一个Plunkr请参阅form.component.spec文件),它证明了这个问题。在同一个文件中还有一个工作解决方案。

所以总之,为了使这项工作,你需要使用fakeAsync机制。

所以不是:

it('testing form the wrong way',() => { 

    fixture.detectChanges(); 

    comp.onSubmit(); // Validates and submits a form 

    expect(comp.submitted).toEqual(false); 
    }); 

你应该写这样一个测试:

it('testing form the proper way', fakeAsync(() => { 

    // This first detectChanges is necessary to properly set up the form 
    fixture.detectChanges(); 

    // Tick needs to be called in order for form controls to be registered properly. 
    tick(); 

    comp.onSubmit(); // Validates and submits a form 

    expect(comp.submitted).toEqual(false); 

    }));