Angular 测试 switchMap 调用调用 0 次
Angular testing switchMap call called 0 times
在我的 Angular 组件中我有这个代码:
delete(post: PostInterface): void {
const delete$ = this.appDataService.proxy
.delete(post, this.paginate)
.pipe(switchMap(() => this.loadDatas()));
this.subscriptions.add(
this.appDataService.start(delete$, 'delete').subscribe()
);
}
我有这个测试:
beforeEach(async () => {
loadDatasSpy = spyOn(component, 'loadDatas').and.returnValue(of(paginate));
});
it('should call proxy.delete with model on call delete', fakeAsync(() => {
loadDatasSpy.calls.reset();
const id = 1;
const post: PostInterface = new Post().init({id});
const proxySpy = jasmine.createSpyObj('ProxyService', ['delete']);
proxySpy.delete.and.returnValue(of(id));
const appDataServiceSpy = jasmine.createSpyObj('AppDataService', ['proxy', 'start']);
appDataServiceSpy.start.and.returnValue(of(id));
appDataServiceSpy.proxy = proxySpy;
component.appDataService = appDataServiceSpy;
component.delete(post);
flush();
// ✔️ this expectation is passes
expect(component.appDataService.proxy.delete)
.withContext('appDataService.proxy.delete')
.toHaveBeenCalledTimes(1);
// ✔️ this expectation is passes
expect(component.appDataService.proxy.delete)
.withContext('appDataService.proxy.delete')
.toHaveBeenCalledWith(post, component.paginate);
// ✔️ this expectation is passes
expect(component.appDataService.start)
.withContext('appDataService.start')
.toHaveBeenCalledTimes(1);
// ❌ this expectation is fail
expect(component.loadDatas).toHaveBeenCalledTimes(1);
}));
最后的期望失败并显示此消息:
Expected spy loadDatas to have been called once. It was called 0 times.
我认为 switchMap
导致了这个问题,但我不知道为什么。我尝试在上面的测试代码上应用 flushMicrotasks()
、tick()
,并与 fixture.whenStabel()
结合但没有成功。
任何 ide 我该如何解决这个问题?
我也将不胜感激。
您必须使用 done() 而不是 fakeAsync。 fakeAsync 会等待,但订阅不会完成。 done() 函数将“触发”rxjs 运算符,您可以在订阅观察者中测试结果。
我是这样想的:
it('should call proxy.delete with model on call delete', (done) => {
...
component.delete(post);
component.appDataService.start.subscribe(() => {
expect(component.appDataService.proxy.delete)
.withContext('appDataService.proxy.delete')
.toHaveBeenCalledTimes(1);
...
expect(component.loadDatas).toHaveBeenCalledTimes(1);
}
done();
}
在我的 Angular 组件中我有这个代码:
delete(post: PostInterface): void {
const delete$ = this.appDataService.proxy
.delete(post, this.paginate)
.pipe(switchMap(() => this.loadDatas()));
this.subscriptions.add(
this.appDataService.start(delete$, 'delete').subscribe()
);
}
我有这个测试:
beforeEach(async () => {
loadDatasSpy = spyOn(component, 'loadDatas').and.returnValue(of(paginate));
});
it('should call proxy.delete with model on call delete', fakeAsync(() => {
loadDatasSpy.calls.reset();
const id = 1;
const post: PostInterface = new Post().init({id});
const proxySpy = jasmine.createSpyObj('ProxyService', ['delete']);
proxySpy.delete.and.returnValue(of(id));
const appDataServiceSpy = jasmine.createSpyObj('AppDataService', ['proxy', 'start']);
appDataServiceSpy.start.and.returnValue(of(id));
appDataServiceSpy.proxy = proxySpy;
component.appDataService = appDataServiceSpy;
component.delete(post);
flush();
// ✔️ this expectation is passes
expect(component.appDataService.proxy.delete)
.withContext('appDataService.proxy.delete')
.toHaveBeenCalledTimes(1);
// ✔️ this expectation is passes
expect(component.appDataService.proxy.delete)
.withContext('appDataService.proxy.delete')
.toHaveBeenCalledWith(post, component.paginate);
// ✔️ this expectation is passes
expect(component.appDataService.start)
.withContext('appDataService.start')
.toHaveBeenCalledTimes(1);
// ❌ this expectation is fail
expect(component.loadDatas).toHaveBeenCalledTimes(1);
}));
最后的期望失败并显示此消息:
Expected spy loadDatas to have been called once. It was called 0 times.
我认为 switchMap
导致了这个问题,但我不知道为什么。我尝试在上面的测试代码上应用 flushMicrotasks()
、tick()
,并与 fixture.whenStabel()
结合但没有成功。
任何 ide 我该如何解决这个问题?
我也将不胜感激。
您必须使用 done() 而不是 fakeAsync。 fakeAsync 会等待,但订阅不会完成。 done() 函数将“触发”rxjs 运算符,您可以在订阅观察者中测试结果。
我是这样想的:
it('should call proxy.delete with model on call delete', (done) => {
...
component.delete(post);
component.appDataService.start.subscribe(() => {
expect(component.appDataService.proxy.delete)
.withContext('appDataService.proxy.delete')
.toHaveBeenCalledTimes(1);
...
expect(component.loadDatas).toHaveBeenCalledTimes(1);
}
done();
}