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

如何使用Karma-Jasmine为动态JSON配置文件编写测试用例

Angular动态配置服务Karma+Jasmine测试实现方案

核心测试覆盖点

测试需要覆盖以下核心逻辑,保证动态配置流程符合预期:

  • 服务实例可正常创建
  • 配置加载方法执行前,config getter默认返回undefined
  • loadConfiguration方法会向正确的路径发起GET请求,请求成功后正确缓存配置值,且返回值与缓存值一致
  • loadConfiguration请求失败时会正确抛出异常,且不会污染缓存的配置值
  • APP_INITIALIZER注册的工厂函数会正确触发配置加载逻辑,保证应用初始化前完成配置读取

具体实现代码

依赖准备

单元测试不需要发起真实HTTP请求,使用Angular官方提供的HttpClientTestingModule拦截请求做mock即可,首先调整测试文件的引入项:

import { TestBed, Injector } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { ConfigurationService } from './configuration.service';
import { configLoader } from './app.module'; // 按项目实际路径调整

ConfigurationService单元测试

替换原有configuration.service.spec.ts中的测试逻辑,覆盖服务核心行为:

describe('ConfigurationService', () => {
  let service: ConfigurationService;
  let httpMock: HttpTestingController;
  // 测试用固定配置路径和mock配置值
  const TEST_CONFIG_PATH = '../assets/demo/data/config.json';
  const MOCK_VALID_CONFIG = {
    sampleConfigValue: 'mock config value for test'
  };

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule]
    });
    service = TestBed.inject(ConfigurationService);
    httpMock = TestBed.inject(HttpTestingController);
  });

  // 每个用例执行完后校验没有未处理的多余请求
  afterEach(() => {
    httpMock.verify();
  });

  it('should be created successfully', () => {
    expect(service).toBeTruthy();
  });

  it('should return undefined for config property before loadConfiguration is called', () => {
    expect(service.config).toBeUndefined();
  });

  it('should load config from correct path, cache value and return config when request succeeds', async () => {
    // 触发配置加载,先不等待Promise完成
    const loadTask = service.loadConfiguration();

    // 拦截发起的HTTP请求,校验请求方法和路径
    const req = httpMock.expectOne(TEST_CONFIG_PATH);
    expect(req.request.method).toBe('GET');

    // 返回mock的成功响应
    req.flush(MOCK_VALID_CONFIG);

    // 等待加载逻辑执行完成
    const returnedValue = await loadTask;

    // 校验返回值和缓存值一致
    expect(returnedValue).toEqual(MOCK_VALID_CONFIG);
    expect(service.config).toEqual(MOCK_VALID_CONFIG);
  });

  it('should reject with error and keep config as undefined when request fails', async () => {
    const loadTask = service.loadConfiguration();
    const req = httpMock.expectOne(TEST_CONFIG_PATH);

    // 模拟404错误响应
    req.flush('Config file not found', { status: 404, statusText: 'Not Found' });

    // 校验Promise异常抛出
    await expectAsync(loadTask).toBeRejected();
    // 校验加载失败时配置缓存未被污染
    expect(service.config).toBeUndefined();
  });
});

APP_INITIALIZER工厂函数测试

单独验证初始化工厂逻辑,保证应用启动时会触发配置加载:

describe('APP_INITIALIZER Config Loader', () => {
  let injector: Injector;
  let configServiceSpy: jasmine.SpyObj<ConfigurationService>;

  beforeEach(() => {
    // 创建ConfigurationService的mock spy对象
    const serviceSpy = jasmine.createSpyObj('ConfigurationService', ['loadConfiguration']);
    TestBed.configureTestingModule({
      providers: [
        { provide: ConfigurationService, useValue: serviceSpy }
      ]
    });
    injector = TestBed.inject(Injector);
    configServiceSpy = TestBed.inject(ConfigurationService) as jasmine.SpyObj<ConfigurationService>;
  });

  it('should generate init function that triggers ConfigurationService.loadConfiguration', () => {
    // mock加载方法返回成功Promise
    configServiceSpy.loadConfiguration.and.returnValue(Promise.resolve({
      sampleConfigValue: 'mock config value for test'
    }));
    
    // 执行工厂得到初始化钩子函数
    const initHook = configLoader(injector);
    initHook();

    // 校验配置加载方法被正确调用
    expect(configServiceSpy.loadConfiguration).toHaveBeenCalledTimes(1);
  });
});

测试说明

  • 所有HTTP请求通过HttpTestingController拦截,不会发起真实网络请求,测试执行速度快、稳定性高
  • afterEach中调用httpMock.verify()可以自动检测是否存在意外发起的未处理请求,避免漏测请求逻辑
  • 如果你使用的RxJS版本>=7,建议将服务中toPromise()替换为firstValueFrom(从rxjs导入),该API在新版本中替代了废弃的toPromise,上述测试用例不需要调整即可兼容
  • 如果需要做全链路集成测试,可以在AppComponent测试中校验应用启动后ConfigurationService.config存在正确值,单元测试阶段覆盖上述逻辑即可满足要求

内容的提问来源于stack exchange,提问作者ftslaptop pc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 14:39:53