如何使用Jest为Angular 12中subscribe内部的代码编写单元测试
Jest测试Angular Observable subscribe内部逻辑示例(适配Angular 12)
默认你已经完成Angular 12项目的Jest基础配置,包含jest-preset-angular相关依赖安装、配置文件初始化。以下是完整的测试示例:
1. 待测试业务代码示例
先给出常见的业务场景代码,方便对照测试逻辑:
// user.service.ts 依赖的服务层代码 import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; import { HttpClient } from '@angular/common/http'; export interface User { id: number; name: string; } @Injectable({ providedIn: 'root' }) export class UserService { constructor(private http: HttpClient) {} getUser(id: number): Observable<User> { return this.http.get<User>(`/api/user/${id}`); } }
// user.component.ts 待测试的组件代码 import { Component, OnInit } from '@angular/core'; import { UserService, User } from './user.service'; @Component({ selector: 'app-user', template: '<p>{{userName}}</p>' }) export class UserComponent implements OnInit { userName: string = ''; requestError: boolean = false; constructor(private userService: UserService) {} ngOnInit(): void { this.loadUserInfo(1); } loadUserInfo(userId: number): void { this.userService.getUser(userId).subscribe({ next: (res) => { this.userName = res.name; // 要测试的next分支逻辑 }, error: () => { this.requestError = true; // 要测试的error分支逻辑 } }) } }
2. 单元测试用例代码
测试核心思路是Mock依赖的服务方法,返回可控的Observable,验证subscribe内部逻辑执行结果是否符合预期:
// user.component.spec.ts 测试文件 import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing'; import { UserComponent } from './user.component'; import { UserService } from './user.service'; import { of, throwError, delay } from 'rxjs'; // Mock依赖的UserService,避免调用真实接口 class MockUserService { getUser = jest.fn(); } describe('UserComponent', () => { let component: UserComponent; let fixture: ComponentFixture<UserComponent>; let userService: UserService; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [UserComponent], providers: [ { provide: UserService, useClass: MockUserService } ] }).compileComponents(); fixture = TestBed.createComponent(UserComponent); component = fixture.componentInstance; userService = TestBed.inject(UserService); fixture.detectChanges(); }); // 测试subscribe next分支逻辑 it('should set userName correctly when getUser request success', () => { const mockUser = { id: 1, name: 'Test User' }; // Mock服务返回成功的Observable (userService.getUser as jest.Mock).mockReturnValue(of(mockUser)); component.loadUserInfo(1); expect(userService.getUser).toHaveBeenCalledWith(1); expect(component.userName).toBe('Test User'); expect(component.requestError).toBe(false); }); // 测试subscribe error分支逻辑 it('should set requestError to true when getUser request fail', () => { // Mock服务返回错误的Observable (userService.getUser as jest.Mock).mockReturnValue(throwError(() => new Error('request fail'))); component.loadUserInfo(1); expect(component.requestError).toBe(true); expect(component.userName).toBe(''); }); // 异步Observable场景测试(比如接口有延迟、加了delay操作符) it('should handle async Observable correctly', fakeAsync(() => { const mockUser = { id: 1, name: 'Async User' }; (userService.getUser as jest.Mock).mockReturnValue(of(mockUser).pipe(delay(200))); component.loadUserInfo(1); tick(200); // 快进时间200ms,触发异步逻辑执行 expect(component.userName).toBe('Async User'); })); });
3. 注意事项
- 所有外部依赖的方法都要提前Mock,保证测试的隔离性,不要调用真实的后端接口
- 如果subscribe内部调用了其他组件方法,可以用
jest.spyOn监听方法的调用状态、入参,验证执行逻辑是否符合预期
内容的提问来源于stack exchange,提问作者Arpitha Mamidala
相关产品推荐
相关产品推荐

