测试用例报错:TypeError: Cannot read properties of undefined (reading 'subscribe')
解决 "TypeError: Cannot read properties of undefined (reading 'subscribe')" 错误
错误场景
执行测试用例时触发以下错误:
TypeError: Cannot read properties of undefined (reading 'subscribe')
服务代码(report.service.ts)
saveReport(reportData: any, reportType: string, reportId: string, reportExists: boolean): Observable<any> { const url = environment.META_API_ROOT + `/cat/report?reportType=` + reportType + (reportId ? `&reportId=${reportId}` : '') + `&reportExists=${reportExists}`; return this.http.post(url, reportData); }
测试用例代码
it('should successfully call endpoint', (done) => { td.when(http.post(environment.API_ROOT + `/cat/report?reportType=reportType`, 'reportData')).thenReturn( of(Builder<Report>().calendarYears([2024]).build()), ); service.saveReport('reportData', 'reportType', null, false).subscribe((result) => { expect(result).toEqual(Builder<Report>().calendarYears([2024).build()); done(); }); });
问题分析
错误核心是service.saveReport(...)返回了undefined而非预期的Observable,导致调用subscribe时出错,具体原因有三点:
- API根地址不匹配:服务代码用
environment.META_API_ROOT拼接URL,但测试用例模拟的是environment.API_ROOT,mock规则不生效,http.post未返回预设的Observable。 - URL参数不全:服务生成的URL会追加
&reportExists=false(传入的reportExists为false),但测试用例的mock URL仅包含?reportType=reportType,参数不匹配导致mock未触发。 - 语法错误:测试用例中
Builder<Report>().calendarYears([2024).build()多了一个左括号,应为[2024],语法错误会导致代码执行异常。
修复方案
修改测试用例,逐一解决上述问题:
it('should successfully call endpoint', (done) => { // 1. 使用和服务一致的API根地址,补全完整URL参数 const mockUrl = environment.META_API_ROOT + `/cat/report?reportType=reportType&reportExists=false`; td.when(http.post(mockUrl, 'reportData')).thenReturn( of(Builder<Report>().calendarYears([2024]).build()), ); service.saveReport('reportData', 'reportType', null, false).subscribe((result) => { // 2. 修复Builder的语法错误 expect(result).toEqual(Builder<Report>().calendarYears([2024]).build()); done(); }); });
为提升测试健壮性,建议用参数匹配器替代硬编码URL,避免参数变化导致mock失效:
td.when(http.post( jasmine.stringContaining('/cat/report'), jasmine.any(String) )).thenReturn(of(Builder<Report>().calendarYears([2024]).build()));
内容的提问来源于stack exchange,提问作者user3633028
相关产品推荐
相关产品推荐

