Angular单元测试:subscribe无返回值致portfolioType为空的问题
Angular组件单元测试中portfolioType值为空的原因及解决方法
在Angular项目中,组件通过getPortfolioType方法调用dataService的getPortfolioTypeList接口,在subscribe回调中为portfolioType赋值,但单元测试调用该方法后,portfolioType始终为空。
相关代码
组件代码(component.ts)
getPortfolioType() { this.dataService.getPortfolioTypeList() .subscribe((response: any) => { this.portfolioType = response.payload.portfolioList; }) }
DataService代码(data.service.ts)
public getPortfolioTypeList(): any { return this.http.getData('/portfolio/portfolioTypeList'); }
HttpService代码(http.service.ts)
getData(action: any, data: any = {}): any { const url = environment.API_URL + action; const params = Object.keys(data); let httpParams = new HttpParams(); if (params.length) { params.forEach((key: string) => { httpParams = httpParams.append(key, data[key]); }); } return this.http.get(url, {params: httpParams}); }
已通过的服务测试用例
it('should pass service getPortfolioTypeList', () => { const test = { "test": "test" } let result: any; dataService.getPortfolioTypeList().subscribe(t => { result = t; }); const req = httpMock.expectOne({ method: "GET", url: environment.API_URL + '/portfolio/portfolioTypeList' }); req.flush([test]); expect(result[0]).toEqual(test); });
失败的组件测试用例
it('Get data from getPortfolioType', () => { component.getPortfolioType(); console.log(component.portfolioType); // <<<< is empty });
原因分析
- 异步操作未完成:
getPortfolioType内部是异步HTTP请求,调用component.getPortfolioType()后,代码会直接执行后续的console.log,此时subscribe回调还未触发,portfolioType自然为空。 - 未模拟HTTP请求并返回数据:组件测试中没有像服务测试那样,用
HttpTestingController捕获请求并返回模拟数据,导致dataService的Observable从未发出值,回调也就不会执行。
解决方法
修改组件测试用例,完成以下步骤:
- 调用组件方法后,捕获对应的HTTP请求;
- 用
flush返回符合组件期望格式的模拟数据; - 触发变更检测(若组件使用OnPush策略则需要);
- 断言
portfolioType的值。
修正后的测试用例示例:
it('Get data from getPortfolioType', () => { // 调用组件方法 component.getPortfolioType(); // 捕获HTTP请求 const req = httpMock.expectOne({ method: "GET", url: environment.API_URL + '/portfolio/portfolioTypeList' }); // 返回符合组件期望格式的模拟数据 const mockResponse = { payload: { portfolioList: [{ id: 1, name: 'Type A' }] } }; req.flush(mockResponse); // 触发变更检测 fixture.detectChanges(); // 断言portfolioType已被赋值 expect(component.portfolioType).toEqual(mockResponse.payload.portfolioList); });
内容的提问来源于stack exchange,提问作者aleksandr_sven
相关产品推荐
相关产品推荐

