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

Angular 18组件单元测试报错:无HttpClient提供者

问题描述

我基于Angular 18开发应用,有一个依赖服务的组件,该服务通过HttpClient获取实体列表,组件在构造函数中注入此服务。服务的单元测试用provideHttpClient和provideHttpClientTesting能正常运行,但组件单元测试却因HttpClient注入失败报错:

Chrome 126.0.0.0 (Windows 10) CardListComponent should create FAILED
NullInjectorError: R3InjectorError(Standalone[CardListComponent])[HttpClient -> HttpClient -> HttpClient]:
NullInjectorError: No provider for HttpClient!
error properties: Object({ ngTempTokenPath: null, ngTokenPath: [ 'HttpClient', 'HttpClient', 'HttpClient' ] })

我试了多种方案(包括官方文档的方法)都没用,以下是我的组件单元测试代码:

describe('CardListComponent', () => {
  let component: CardListComponent;
  let fixture: ComponentFixture<CardListComponent>;

  let cardService: CardServiceService;

  const cardServiceMock: jasmine.SpyObj<CardServiceService> = jasmine.createSpyObj('CardServiceService', ['getAllCards']);

 beforeEach(async () => {
   await TestBed.configureTestingModule({
     imports: [CardListComponent],
     providers: [
       provideHttpClient,
       provideHttpClientTesting,
       CardListComponent,
         {
        provide: CardServiceService,
         useValue: cardServiceMock,
       },
    ],
  }).compileComponents();

fixture = TestBed.createComponent(CardListComponent);

component = fixture.componentInstance;

fixture.detectChanges();
});
it('should create', () => {
  expect(component).toBeTruthy();
});

解决方案

问题核心在于你已经用Mock替代了真实的CardServiceService,但测试配置中冗余添加了HttpClient相关提供者,还错误地将组件本身放进了providers数组,导致注入逻辑混乱。

修改步骤:

  1. 移除providers中的provideHttpClient和provideHttpClientTesting:Mock服务不会依赖真实的HttpClient,完全不需要这些配置。
  2. 移除providers中的CardListComponent:独立组件只需在imports中导入,重复放进providers会引发注入冲突。
  3. 给Mock的getAllCards方法设置返回值:组件初始化时会调用该方法,若无返回值会导致订阅报错。

修改后的测试代码

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CardListComponent } from './card-list.component';
import { CardServiceService } from '../services/card-service.service';
import { of } from 'rxjs';

describe('CardListComponent', () => {
  let component: CardListComponent;
  let fixture: ComponentFixture<CardListComponent>;
  const cardServiceMock: jasmine.SpyObj<CardServiceService> = jasmine.createSpyObj('CardServiceService', ['getAllCards']);

  beforeEach(async () => {
    // 给Mock方法设置空数组返回值,避免组件订阅出错
    cardServiceMock.getAllCards.and.returnValue(of([]));

    await TestBed.configureTestingModule({
      imports: [CardListComponent],
      providers: [
        {
          provide: CardServiceService,
          useValue: cardServiceMock,
        },
      ],
    }).compileComponents();

    fixture = TestBed.createComponent(CardListComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

内容的提问来源于stack exchange,提问作者Luiz Gustavo Mendes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 12:23:22