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数组,导致注入逻辑混乱。
修改步骤:
- 移除
providers中的provideHttpClient和provideHttpClientTesting:Mock服务不会依赖真实的HttpClient,完全不需要这些配置。 - 移除
providers中的CardListComponent:独立组件只需在imports中导入,重复放进providers会引发注入冲突。 - 给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
相关产品推荐
相关产品推荐

