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

Angular Jasmine单元测试:如何Mock组件调用服务内的HTTP请求返回结果

Angular Karma/Jasmine 单元测试实现方案

你不需要在组件单元测试中模拟服务内部的HTTP请求,因为你已经通过spy替换了RandomService的getRandomItems对外方法,直接控制该方法的返回值即可完成组件逻辑验证。如果需要单独验证服务内部的HTTP处理逻辑,再使用Angular提供的HttpClientTestingModule模拟HTTP请求即可。

组件单元测试实现(验证getPlans方法逻辑)

直接构造符合你预期顺序的RandomItem数组,作为spy的返回值即可:

import { of, throwError } from 'rxjs';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PlansComponent } from './plans.component';
import { RandomService } from './random.service';
// 其他类型导入省略

describe('PlansComponent', () => {
  let component: PlansComponent;
  let fixture: ComponentFixture<PlansComponent>;
  let randomSpy: jasmine.SpyObj<RandomService>;

  beforeEach(async () => {
    // 初始化服务Spy
    const spy = jasmine.createSpyObj('RandomService', ['getRandomItems']);

    await TestBed.configureTestingModule({
      declarations: [PlansComponent],
      providers: [
        { provide: RandomService, useValue: spy }
      ]
    }).compileComponents();

    randomSpy = TestBed.inject(RandomService) as jasmine.SpyObj<RandomService>;
  });

  it('getPlans执行后应该正确拆分活跃/非活跃条目,且顺序符合预期', () => {
    // 按照服务调整后的返回顺序构造模拟数据
    const mockItems: RandomItem[] = [
      { id: 'active_1', isActive: true, name: '活跃条目1' },
      { id: 'active_2', isActive: true, name: '活跃条目2' },
      { id: 'pending_1', isActive: false, name: '待处理条目1' },
      { id: 'pending_2', isActive: false, name: '待处理条目2' }
    ];
    // 设置Spy返回模拟数据
    randomSpy.getRandomItems.and.returnValue(of(mockItems));

    // 初始化组件,触发构造函数内的getPlans调用
    fixture = TestBed.createComponent(PlansComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();

    // 断言结果符合预期
    expect(randomSpy.getRandomItems).toHaveBeenCalledWith(component.id);
    expect(component.activeItems.length).toBe(2);
    expect(component.activeItems[0].id).toBe('active_1'); // 验证顺序
    expect(component.randomItems.length).toBe(2);
    expect(component.randomItems[0].id).toBe('pending_1');
    expect(component.loading).toBeFalse();
  });

  it('getPlans请求失败时应该触发错误处理', () => {
    const mockError: ResponseError = { code: 500, message: '请求异常' };
    randomSpy.getRandomItems.and.returnValue(throwError(() => mockError));
    // 监听错误处理方法
    spyOn(component, 'handleError');

    fixture = TestBed.createComponent(PlansComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();

    expect(component.handleError).toHaveBeenCalledWith(mockError);
    expect(component.loading).toBeFalse();
  });
});

服务单元测试实现(验证内部HTTP请求处理逻辑)

如果需要单独验证RandomService中getRandomItems方法对接口返回值的拼接逻辑,使用HttpClientTestingModule模拟HTTP请求:

import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { RandomService } from './random.service';

describe('RandomService', () => {
  let service: RandomService;
  let httpTestingController: HttpTestingController;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [RandomService]
    });
    service = TestBed.inject(RandomService);
    httpTestingController = TestBed.inject(HttpTestingController);
  });

  it('getRandomItems应该正确拼接活跃条目和待处理条目返回', () => {
    const testId = 'test_id_123';
    // 模拟接口原始返回值
    const mockApiRes = {
      activeItem: [
        { id: 'a1', isActive: true },
        { id: 'a2', isActive: true }
      ],
      pendingItem: [
        { id: 'p1', isActive: false },
        { id: 'p2', isActive: false }
      ]
    };

    service.getRandomItems(testId).subscribe(result => {
      // 断言返回数组顺序为活跃条目在前,待处理条目在后
      expect(result.length).toBe(4);
      expect(result[0].id).toBe('a1');
      expect(result[2].id).toBe('p1');
    });

    // 验证请求地址、方法符合预期
    const req = httpTestingController.expectOne(`/items/${testId}/getRandomItems`);
    expect(req.request.method).toBe('GET');
    // 注入模拟接口返回值
    req.flush(mockApiRes);
    // 验证无多余请求
    httpTestingController.verify();
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 05:45:03