Angular6 Jasmine-Karma如何测试调用API返回subscribe的方法及ngOnInit
Angular 6 基于Jasmine-Karma的订阅方法与ngOnInit测试方案
你原有测试存在两个核心问题:
- 创建
subSpy时调用了一次service.getAllAccounts(),得到的是全新的Observable实例,和组件调用时拿到的实例完全无关,所以这个spy永远不会触发,属于无效监听 - 第二个用例没有提前给service的
getAllAccounts方法绑定mock返回值,直接调用ngOnInit后allAccounts不会被赋值,断言会失败
前置配置
首先在测试套件的beforeEach中完成依赖注入和service的预mock,避免真实发起HTTP请求:
// 替换为你自己的组件、服务名 import { YourComponent } from './your.component'; import { YourAccountService } from './your-account.service'; import { of } from 'rxjs'; describe('YourComponent', () => { let component: YourComponent; let fixture: ComponentFixture<YourComponent>; let service: jasmine.SpyObj<YourAccountService>; // 提前定义mock的接口返回数据 const mockAccountList = [ {id: 1, name: '测试账户1'}, {id: 2, name: '测试账户2'}, {id: 3, name: '测试账户3'}, {id: 4, name: '测试账户4'}, {id: 5, name: '测试账户5'}, {id: 6, name: '测试账户6'}, ]; beforeEach(async () => { // 创建service的mock对象 const serviceSpy = jasmine.createSpyObj('YourAccountService', ['getAllAccounts']); await TestBed.configureTestingModule({ declarations: [ YourComponent ], providers: [ { provide: YourAccountService, useValue: serviceSpy } ] }) .compileComponents(); fixture = TestBed.createComponent(YourComponent); component = fixture.componentInstance; // 注入mock的service实例 service = TestBed.inject(YourAccountService) as jasmine.SpyObj<YourAccountService>; // 预配置service方法的返回值 service.getAllAccounts.and.returnValue(of(mockAccountList)); }); });
ngOnInit测试逻辑
ngOnInit本身只负责调用getAllAccounts,所以测试只要验证这个调用行为即可,不需要测试内部方法的逻辑:
it('ngOnInit执行时应调用getAllAccounts方法', () => { // 监听组件的getAllAccounts方法 const methodSpy = spyOn(component, 'getAllAccounts'); // 手动触发生命周期钩子 component.ngOnInit(); // 验证调用次数 expect(methodSpy).toHaveBeenCalledTimes(1); });
getAllAccounts订阅逻辑测试
因为我们用of()返回的是同步Observable,订阅回调会立刻执行,不需要用到fakeAsync、tick等异步处理工具:
it('getAllAccounts应调用服务端的getAllAccounts接口', () => { component.getAllAccounts(); expect(service.getAllAccounts).toHaveBeenCalledTimes(1); }); it('getAllAccounts订阅成功后应正确赋值allAccounts变量', () => { component.getAllAccounts(); expect(component.allAccounts).toBeDefined(); expect(component.allAccounts.length).toBeGreaterThan(5); // 也可以直接验证和mock数据完全相等 expect(component.allAccounts).toEqual(mockAccountList); });
注意:不需要单独监听subscribe方法,只要验证接口被调用、返回值赋值正确,即可证明订阅逻辑正常运行,额外监听subscribe属于冗余测试,还容易因为实例不同导致用例失败
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

