Angular服务中if语句的单元测试覆盖问题
问题描述
我有一个Service 1,内部调用Service 2获取数据,返回数据前会在Service 1中进行数据校验。核心代码如下:
getuserImageUrl(Id: number): Observable<string> { return this.getUserDetailsAPI(Id) .pipe( map((userInfo: any) => { console.log(userInfo); let url = userInfo.url; if (url === undefined || url === null) { return ''; } return url; }) ) .pipe( catchError((error) => { console.log(error); return ''; }) ); }
我编写了以下测试用例,但代码覆盖率显示if (url === undefined || url === null)代码块未被覆盖,请问如何在单元测试中覆盖该分支?
测试用例代码:
it('should provide null if image url is null', fakeAsync(() => { userServiceSpy.getUserDetailsAPI.and.returnValue(of("")); userService.getuserImageUrl(Id) .subscribe((data) => { expect(userServiceSpy.getUserDetailsAPI).toHaveBeenCalled(); expect(data).toEqual(''); }); const req1 = httpTestingController.expectOne( `myproject.com/getuserImageUrl/${Id}` ); expect(req1.request.method).toEqual('GET'); req1.flush(""); }));
解决方案
你的测试用例未覆盖目标分支,问题出在两个关键点:
- 模拟返回值不符合代码逻辑:你让
getUserDetailsAPI返回of("")(空字符串),但代码中是从userInfo.url读取属性——空字符串没有url属性,虽然此时url会是undefined,但这种模拟方式不符合业务逻辑的预期输入。正确的做法是返回包含url为null或undefined的对象,精准命中判断分支。 - 冗余的HTTP请求校验:既然已经通过Spy模拟了
getUserDetailsAPI的返回值,该方法的调用会被拦截,不会实际发起HTTP请求,因此httpTestingController相关代码完全多余,甚至会导致测试报错。
你需要针对两个分支分别编写测试用例:
覆盖url为null的场景
it('should return empty string when userInfo.url is null', () => { // 模拟返回包含url: null的用户信息对象 userServiceSpy.getUserDetailsAPI.and.returnValue(of({ url: null })); userService.getuserImageUrl(123).subscribe(data => { expect(data).toBe(''); expect(userServiceSpy.getUserDetailsAPI).toHaveBeenCalledWith(123); }); });
覆盖url为undefined的场景
it('should return empty string when userInfo.url is undefined', () => { // 模拟返回无url属性的对象,此时userInfo.url会是undefined userServiceSpy.getUserDetailsAPI.and.returnValue(of({})); // 也可以直接返回{ url: undefined },效果一致 userService.getuserImageUrl(123).subscribe(data => { expect(data).toBe(''); expect(userServiceSpy.getUserDetailsAPI).toHaveBeenCalledWith(123); }); });
另外,原测试用例中的fakeAsync属于多余用法——如果测试中没有涉及定时器等需要时间控制的异步操作,无需使用fakeAsync,直接编写普通同步测试即可。
内容的提问来源于stack exchange,提问作者anand kumar
相关产品推荐
相关产品推荐

