测试未进入 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();
});
});
我的测试无法覆盖代码的管道部分,不知道哪里出了问题。 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();
});
});