如何在Jasmine中测试错误响应?Angular组件测试问题排查
Angular组件ngOnChanges错误处理测试问题分析与修复
问题场景
组件核心代码:
ngOnChanges() { this.searchCriteria$ = this.bookingService.getSearchCriteria(this.booking.id).pipe( catchError((err) => { this.error$ = of(err); return EMPTY; }) ); }
测试时遇到两个问题:
- 初始测试报错:
TypeError: Cannot read properties of undefined (reading 'subscribe')
测试代码:fit('should set error loading search criteria failed', () => { const errorMessage = 'Error getting search criteria'; bookingService.getSearchCriteria.and.returnValue(throwError(() => new Error(errorMessage))); component.ngOnChanges(); component.error$.subscribe((error) => { expect(error).toBe(errorMessage); }); }); - 添加
component.searchCriteria$.subscribe(() => {})后,报错变为:Expected Error: Error getting search criteria to be 'Error getting search criteria'.
正常响应的测试用例可成功执行,仅错误分支测试失败。
问题原因
- 第一个错误根源:
error$未提前初始化。组件中error$仅在catchError逻辑内赋值,而catchError需要searchCriteria$被订阅才会触发。初始测试未订阅searchCriteria$,导致error$始终为undefined,订阅时触发类型错误。 - 第二个错误根源:
error$接收的是Error对象,测试中直接用字符串errorMessage做全等断言,类型不匹配导致断言失败。
修复方案
步骤1:提前初始化组件内的error$
在组件类中声明error$时直接初始化,避免出现undefined:
error$: Observable<Error | null> = of(null);
步骤2:修正错误分支测试代码
必须订阅searchCriteria$触发流执行,同时断言Error对象的message属性而非直接断言对象:
fit('should set error loading search criteria failed', () => { const errorMessage = 'Error getting search criteria'; bookingService.getSearchCriteria.and.returnValue(throwError(() => new Error(errorMessage))); component.ngOnChanges(); // 订阅searchCriteria$触发catchError逻辑 component.searchCriteria$.subscribe({ complete: () => { // catchError返回EMPTY,流会进入complete阶段 component.error$.subscribe((error) => { expect(error?.message).toBe(errorMessage); }); } }); });
简化写法(使用async/await + toPromise)
fit('should set error loading search criteria failed', async () => { const errorMessage = 'Error getting search criteria'; bookingService.getSearchCriteria.and.returnValue(throwError(() => new Error(errorMessage))); component.ngOnChanges(); // 触发searchCriteria$流执行,catchError返回EMPTY所以不会抛出错误 await component.searchCriteria$.toPromise().catch(() => {}); const error = await component.error$.toPromise(); expect(error?.message).toBe(errorMessage); });
正常分支测试成功的原因
正常分支中getSearchCriteria返回of(searchCriteria),订阅searchCriteria$时流会立即发出值,断言逻辑能直接生效;而错误分支必须触发catchError,所以必须先订阅searchCriteria$才能完成error$的赋值。
内容的提问来源于stack exchange,提问作者programmer24
相关产品推荐
相关产品推荐

