测试未进入 rxjs 运算符管道并点击 Angular 代码

Test is not entering rxjs operator pipe and tap in the Angular code

我的测试无法覆盖代码的管道部分,不知道哪里出了问题。 covereage of the code。我在模板中使用 ngx-chip。 autocompleteObservable 选择标签输入中键入的文本并将其传递给 requestAutocompleteItems,进一步传递给 peopleService 以根据文本获取数据。还有一个微调器,在处理数据前后手动打开和关闭。

component.html

<tag-input
  theme="foundation-theme"
  [placeholder]="placeholder"
  [secondaryPlaceholder]="secondPlaceholder"
  onlyFromAutocomplete="true"
  [animationDuration]="animation"
  [(ngModel)]="items"
  (onAdd)="onItemAdded($event)"
  (onRemove)="onItemRemoved()"
  [maxItems]="maxItems"
  (focusout)="stopLoading()"
>
  <tag-input-dropdown
    [autocompleteObservable]="requestAutocompleteItems"
    [dynamicUpdate]="false"
    [displayBy]="fieldName"
    [identifyBy]="fieldId"
    [minimumTextLength]="numberText"
    [appendToBody]="false"
  >
  </tag-input-dropdown>
</tag-input>
<div class="progress-spinner" *ngIf="showLoading">
  <p-progressSpinner></p-progressSpinner>
</div>

component.ts

ngOnInit() {
    this.requestAutocompleteItems = (text: string): Observable<AutoCompleteItem[]> => {
      this.showLoading = true;
      // Add this to an autocomplete
      let textJson;
      if (this.department) {
        textJson = {
          where: { and: [{ displayName: { like: text } }, { department: { like: this.department } }] },
          include: this.colsIncluded,
        };
      } else {
        textJson = { where: { displayName: { like: text } }, include: this.colsIncluded };
      }
      return this.peopleService.getData(JSON.stringify(textJson)).pipe(
        tap(() => {
          this.showLoading = false;
        }),
      );
    };
  }

component.spec.ts

it('should stop loading', () => {
    peoplePickerServiceSpy.getData.and.returnValue(of({}));
    fixture.detectChanges();
    component.requestAutocompleteItems('erv');
    fixture.detectChanges();
    expect(peoplePickerServiceSpy.getData).toHaveBeenCalled();
  });

您的测试缺少对 requestAutocompleteItems 的订阅。如果没有订阅它,tap 运算符中的代码将永远不会触发。因此,您要么提供一个能够做到这一点的 tag-input 模拟,要么在没有它的情况下进行。对于专家来说,这是一个很好的问题,我们是否关心我们的 observable 在某些子组件中是如何处理的,或者我们不关心。

如果您决定不担心它,您应该将单元测试包装到 fakeAsync 函数,然后在 UT 中订阅 requestAutocompleteItems

it('should stop loading', fakeAsync(() => {
  peoplePickerServiceSpy.getData.and.returnValue(of({}));
  fixture.detectChanges();

  component.requestAutocompleteItems('erv').subscribe(() => {
    expect(peoplePickerServiceSpy.getData).toHaveBeenCalled();
  });
  fixture.detectChanges();

  tick(); //necessary -> simulates the asynchronous passage of time
}));

这就是我解决问题的方法,就像 Mat 所说的那样,它需要一个订阅块来完成可观察的我添加了一个 done 函数。

it('should stop loading', done => {
    peoplePickerServiceSpy.getData.and.returnValue(of({}));
    fixture.detectChanges();
    component.requestAutocompleteItems('erv').subscribe(() => {
      expect(peoplePickerServiceSpy.getData).toHaveBeenCalled();
      done();
    });
  });