如何用Karma/Angular/Jasmine测试Post订阅?测试覆盖率不达标
Angular登录逻辑单元测试覆盖率优化方案
你当前的登录逻辑包含三个未完全覆盖的代码分支:next回调中user.sc === true、user.sc === false,以及error回调,现有测试仅覆盖了第一个分支,这是覆盖率不达标的核心原因。以下是完善后的测试用例,覆盖所有分支并满足覆盖率要求:
1. 测试前置准备
在测试文件的beforeEach中完成依赖注入与必要Mock,避免测试污染:
let component: LoginComponent; let fixture: ComponentFixture<LoginComponent>; let apiService: ApiServicesService; let toastrService: ToastrService; const routerSpy = jasmine.createSpyObj('Router', ['navigate']); beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [LoginComponent], providers: [ ApiServicesService, { provide: ToastrService, useValue: jasmine.createSpyObj('ToastrService', ['success', 'error']) }, { provide: Router, useValue: routerSpy } ] }).compileComponents(); fixture = TestBed.createComponent(LoginComponent); component = fixture.componentInstance; apiService = TestBed.inject(ApiServicesService); toastrService = TestBed.inject(ToastrService); // Mock localStorage操作 spyOn(localStorage, 'setItem'); spyOn(localStorage, 'getItem'); });
2. 测试登录成功分支(user.sc === true)
优化原有测试,去除冗余断言,验证所有关键行为:
it('should handle successful login when user.sc is true', () => { const successResponse = { sc: true, result: { first_name: 'Test', last_name: 'User', token: 'test-token-123' } }; spyOn(apiService, 'post').and.returnValue(of(successResponse)); component.onSubmit(); expect(apiService.post).toHaveBeenCalledWith('/login', component.loginForm.value); expect(localStorage.setItem).toHaveBeenCalledWith('firstName', successResponse.result.first_name); expect(localStorage.setItem).toHaveBeenCalledWith('lastName', successResponse.result.last_name); expect(localStorage.setItem).toHaveBeenCalledWith('token', successResponse.result.token); expect(component.loading).toBe(false); expect(toastrService.success).toHaveBeenCalledWith('Login successful'); expect(routerSpy.navigate).toHaveBeenCalledWith(['/under-construction']); expect(component.isSubmitted).toBe(false); expect(component.loginForm.pristine).toBe(true); });
3. 测试登录失败分支(user.sc === false)
新增该分支测试,验证错误提示与状态重置:
it('should handle failed login when user.sc is false', () => { const failResponse = { sc: false, error: { msg: 'Invalid username or password' } }; spyOn(apiService, 'post').and.returnValue(of(failResponse)); component.onSubmit(); expect(apiService.post).toHaveBeenCalledWith('/login', component.loginForm.value); expect(component.loading).toBe(false); expect(toastrService.error).toHaveBeenCalledWith(failResponse.error.msg); expect(component.isSubmitted).toBe(false); expect(localStorage.setItem).not.toHaveBeenCalled(); expect(routerSpy.navigate).not.toHaveBeenCalled(); });
4. 测试API请求错误分支
新增错误回调测试,验证服务端异常处理:
it('should handle API request error', () => { const apiError = { error: { error: { msg: 'Server connection failed' } } }; spyOn(apiService, 'post').and.returnValue(throwError(() => apiError)); component.onSubmit(); expect(apiService.post).toHaveBeenCalledWith('/login', component.loginForm.value); expect(component.loading).toBe(false); expect(toastrService.error).toHaveBeenCalledWith(apiError.error.error.msg); expect(localStorage.setItem).not.toHaveBeenCalled(); expect(routerSpy.navigate).not.toHaveBeenCalled(); });
以上用例覆盖了登录逻辑的所有代码路径,验证了每个分支下的关键行为(存储操作、状态变更、提示调用、路由跳转等),执行ng test --code-coverage即可达标。
内容的提问来源于stack exchange,提问作者vanishree
相关产品推荐
相关产品推荐

