使用Jest与Angular测试组件方法:RxJS Observable场景测试
需求与代码说明
我有一个在选择组件变更时触发的公共方法,该方法仅调用另外两个私有方法。每个私有方法会填充一个被RxJS监听的Observable变量。我需要编写测试用例,覆盖公共方法及两个私有方法:
- 第一个测试用例:验证方法返回列表以填充变量
- 第二个测试用例:验证catchError返回
of([])的场景
这些私有方法中使用了pipe,因为我的服务已配置错误拦截器。
相关变量定义
free$: Observable<ILista[]> | null = null; grant$: Observable<ILista[]> | null = null;
公共方法代码
listagemgeral(event: number) { this.disponiveis(event); this.concedidas(event); }
填充free$的私有方法
private disponiveis(iduser: number) { this.free$ = this.service.listarDisponiveis(iduser).pipe( catchError(() => { return of([]); }) ); }
填充grant$的私有方法
private concedidas(iduser: number) { this.grant$ = this.service.listarConcedidos(iduser).pipe( catchError(() => { return of([]); }) ); }
测试用例示例
1. 验证方法返回列表填充变量
import { TestBed } from '@angular/core/testing'; import { of } from 'rxjs'; import { YourComponent } from './your.component'; import { YourService } from './your.service'; describe('YourComponent', () => { let component: YourComponent; let service: jasmine.SpyObj<YourService>; const mockFreeList: ILista[] = [{ id: 1, name: '免费项1' }, { id: 2, name: '免费项2' }]; const mockGrantList: ILista[] = [{ id: 3, name: '授权项1' }, { id: 4, name: '授权项2' }]; beforeEach(() => { const serviceSpy = jasmine.createSpyObj('YourService', ['listarDisponiveis', 'listarConcedidos']); TestBed.configureTestingModule({ providers: [{ provide: YourService, useValue: serviceSpy }] }); component = TestBed.inject(YourComponent); service = TestBed.inject(YourService) as jasmine.SpyObj<YourService>; }); it('调用listagemgeral后,应通过服务返回的列表填充free$和grant$', () => { // 模拟服务返回成功数据 service.listarDisponiveis.and.returnValue(of(mockFreeList)); service.listarConcedidos.and.returnValue(of(mockGrantList)); // 调用公共方法 component.listagemgeral(1); // 验证服务方法被正确调用 expect(service.listarDisponiveis).toHaveBeenCalledWith(1); expect(service.listarConcedidos).toHaveBeenCalledWith(1); // 订阅Observable验证数据正确性 component.free$.subscribe(data => { expect(data).toEqual(mockFreeList); }); component.grant$.subscribe(data => { expect(data).toEqual(mockGrantList); }); }); });
2. 验证catchError返回of([])的场景
import { TestBed } from '@angular/core/testing'; import { throwError, of } from 'rxjs'; import { YourComponent } from './your.component'; import { YourService } from './your.service'; describe('YourComponent', () => { let component: YourComponent; let service: jasmine.SpyObj<YourService>; beforeEach(() => { const serviceSpy = jasmine.createSpyObj('YourService', ['listarDisponiveis', 'listarConcedidos']); TestBed.configureTestingModule({ providers: [{ provide: YourService, useValue: serviceSpy }] }); component = TestBed.inject(YourComponent); service = TestBed.inject(YourService) as jasmine.SpyObj<YourService>; }); it('服务调用失败时,disponiveis方法应返回空数组', () => { // 模拟服务抛出错误 service.listarDisponiveis.and.returnValue(throwError(() => new Error('请求失败'))); // 调用私有方法(测试场景下通过方括号语法访问私有成员) component['disponiveis'](1); // 订阅验证错误处理后的结果 component.free$.subscribe(data => { expect(data).toEqual([]); }); }); it('服务调用失败时,concedidas方法应返回空数组', () => { service.listarConcedidos.and.returnValue(throwError(() => new Error('请求失败'))); component['concedidas'](1); component.grant$.subscribe(data => { expect(data).toEqual([]); }); }); });
注:测试私有方法时,使用TypeScript方括号语法
component['disponiveis']访问私有成员是测试场景下的常见做法。
内容的提问来源于stack exchange,提问作者Hugo Leonardo
相关产品推荐
相关产品推荐

