You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:29:19