Angular 8 Jest测试:toHaveBeenCalledWith失败,如何验证API调用及数据?
解决Angular SubsystemService测试的两个目标问题
我来帮你调整这个测试文件,搞定你提到的两个测试需求:确保模拟数据匹配ModelSubSystem且能正确获取响应,以及验证HttpClient.get调用了正确的API URL。咱们先看看原测试里的问题,再一步步修正:
原测试的核心问题
你当前的测试用例里,还没调用服务的实际方法(比如service.getSubsystems(),假设这是你服务里获取子系统列表的方法)就直接断言http.get被调用了,这时候http.get根本没执行,所以toHaveBeenCalledWith肯定会失败。另外,也没验证返回的响应是否符合ModelSubSystem的结构。
修改后的完整spec.ts代码
import { TestBed } from '@angular/core/testing'; import { HttpClient } from '@angular/common/http'; import { cold, getTestScheduler } from 'jasmine-marbles'; import { ModelSubSystem } from './../models/model.subSystem'; import { SubsystemService } from './subsystem-service'; describe('SubsystemService', () => { let service: SubsystemService; let http: HttpClient; // 确保模拟数据严格匹配ModelSubSystem类型(不用as断言,直接按接口定义创建) const data1: ModelSubSystem = { Id: 0, Name: 'subsystem1', IsDeletePossible: true, CreatedBy: '', CreatedDate: new Date(), UpdatedBy: '', UpdatedDate: new Date(), UpdatedByName: '', CreatedByName: '' }; const data2: ModelSubSystem = { Id: 1, // 给不同Id让模拟数据更真实 Name: 'subsystem2', IsDeletePossible: true, CreatedBy: '', CreatedDate: new Date(), UpdatedBy: '', UpdatedDate: new Date(), UpdatedByName: '', CreatedByName: '' }; const mockSubsystems: ModelSubSystem[] = [data1, data2]; const expectedApiUrl = `https://ewsanedevaoscmsapi01-as.websites.net/api/SubSystem`; beforeEach(() => { TestBed.configureTestingModule({ providers: [{ provide: HttpClient, useValue: { get: jest.fn() } }] }); service = TestBed.inject(SubsystemService); // 用inject替代get,Angular最新推荐写法 http = TestBed.inject(HttpClient); }); describe('get subsystem collection', () => { it('should call the correct API URL and return valid ModelSubSystem array', () => { // 1. 设置http.get的mock返回,模拟冷Observable const mockResponse = cold('(a|)', { a: mockSubsystems }); jest.spyOn(http, 'get').mockReturnValue(mockResponse); // 2. 调用服务的实际方法(替换成你服务里真实的获取方法名) const result$ = service.getSubsystems(); // 3. 验证http.get是否调用了正确的API URL expect(http.get).toHaveBeenCalledWith(expectedApiUrl); // 4. 验证返回的数据流是否匹配预期的ModelSubSystem数组 const expected$ = cold('(a|)', { a: mockSubsystems }); expect(result$).toBeObservable(expected$); // 触发测试调度器,确保Observable执行完成 getTestScheduler().flush(); }); }); it('should be created', () => { expect(service).toBeTruthy(); }); });
关键修改点说明
- 严格匹配ModelSubSystem类型:把原来的
as ModelSubSystem换成直接指定类型const data1: ModelSubSystem = {...},确保模拟数据完全符合接口定义,避免类型断言带来的潜在问题。 - 调整测试顺序:先设置mock,再调用服务方法,最后做断言——这是测试异步服务的标准流程。
- 验证响应数据:用
toBeObservable结合jasmine-marbles,确保返回的Observable发射的数据是符合预期的ModelSubSystem数组。 - 使用Angular推荐的inject方法:替代旧的
TestBed.get(),更符合Angular最新版本的测试规范。 - 明确API URL常量:把URL抽成常量,方便后续维护和修改。
注意事项
如果你服务里获取子系统的方法名不是getSubsystems,记得把代码里的service.getSubsystems()换成你实际的方法名(比如service.getAllSubsystems()之类的)。
内容的提问来源于stack exchange,提问作者3gwebtrain
相关产品推荐
相关产品推荐

