javascript - 为什么 ngForm "controls"属性在我的测试中为空? ( Angular )

标签 javascript angular unit-testing angular2-forms angular2-testing

我有一个采用模板驱动形式的组件

<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>

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

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

但是,当我尝试使用 Karma 测试此方法时,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);

  }));

关于javascript - 为什么 ngForm "controls"属性在我的测试中为空? ( Angular ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46769953/

相关文章:

javascript - 有没有好的网站性能分析工具? (前端)

javascript - Babel (gulp-babel) 未捕获的 ReferenceError : require is not defined

javascript - p5.j​​s:在 html 元素之上渲染 Canvas 而不阻止鼠标交互

Javascript 集 ES6

javascript - 如何从内容丰富的 CDA 响应中删除 sys 对象?

angular - 测试带有订阅的 typescript 函数

unit-testing - 如何在 salesforce 中执行 "lastmodified"日期的测试类覆盖率?

javascript - 从日历中绑定(bind)选定日期的 Angular 事件是什么?

AngularJS 服务 Jasmine 单元测试未刷新请求错误

reactjs - 使用react-testing-library在useEffect中测试api调用