Angular+Jest测试报错NG0203:无法实例化UserService求助
问题
团队统一使用Jest测试Angular项目,测试UserService时无法完成实例化,触发NG0203错误,怀疑问题出在依赖关联或配置层面。
测试代码
import { TestBed } from '@angular/core/testing'; import { ENVIRONMENT } from '../core'; describe('UserService', () => { let service: UserService; beforeEach(async() => { await TestBed.configureTestingModule({ providers: [UserService, { provide: ENVIRONMENT,useValue: { apiUrl: '/api/', jwtTokenName: 'my.token', } } ]}).compileComponents(); service = TestBed.inject(UserService); }); it('should be created', () => { expect(service).toBeTruthy(); }); });
UserService代码
@Injectable({ providedIn: 'root' }) export class UserService { private _user: ReplaySubject<User> = new ReplaySubject<User>(1); constructor( private _apiService: ApiService, private _socketService: SocketService, ) { this._socketService.emitter.subscribe((event: SocketEvent) => { this.onSocketEvent(event); }); } }
报错输出
FAIL src/app/core/user/user.service.spec.ts ● UserService › should be created NG0203: inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with `EnvironmentInjector#runInContext`. Find more at https://angular.io/errors/NG0203
解决方案
NG0203错误的核心原因是依赖未正确提供,导致注入上下文失效。你的UserService构造函数依赖了ApiService和SocketService,但测试模块的providers中仅声明了UserService和ENVIRONMENT,未提供这两个关键依赖,因此实例化时触发注入错误。
解决方法一:手动提供依赖的模拟实现
在TestBed的providers中添加两个依赖的模拟对象,确保模拟对象包含UserService构造函数中用到的属性(比如SocketService的emitter):
import { Subject } from 'rxjs'; describe('UserService', () => { let service: UserService; beforeEach(async() => { // 模拟ApiService const mockApiService = {}; // 模拟SocketService,构造函数中订阅了emitter,需提供Subject实例 const mockSocketService = { emitter: new Subject<SocketEvent>() }; await TestBed.configureTestingModule({ providers: [ UserService, { provide: ENVIRONMENT, useValue: { apiUrl: '/api/', jwtTokenName: 'my.token' } }, { provide: ApiService, useValue: mockApiService }, { provide: SocketService, useValue: mockSocketService } ] }).compileComponents(); service = TestBed.inject(UserService); }); it('should be created', () => { expect(service).toBeTruthy(); }); });
解决方法二:简化测试配置(移除不必要的async/await)
Angular CLI项目中组件模板已预编译,无需调用compileComponents(),可简化测试代码,同时确保注入上下文正确:
import { Subject } from 'rxjs'; describe('UserService', () => { let service: UserService; beforeEach(() => { TestBed.configureTestingModule({ providers: [ UserService, { provide: ENVIRONMENT, useValue: { apiUrl: '/api/', jwtTokenName: 'my.token' } }, { provide: ApiService, useValue: {} }, { provide: SocketService, useValue: { emitter: new Subject<SocketEvent>() } } ] }); service = TestBed.inject(UserService); }); it('should be created', () => { expect(service).toBeTruthy(); }); });
解决方法三:使用Jest自动模拟依赖
在测试文件顶部通过jest.mock自动生成依赖服务的模拟类,再在providers中声明使用:
// 替换为实际的文件路径 jest.mock('../../api.service'); jest.mock('../../socket.service'); describe('UserService', () => { let service: UserService; beforeEach(() => { TestBed.configureTestingModule({ providers: [ UserService, { provide: ENVIRONMENT, useValue: { apiUrl: '/api/', jwtTokenName: 'my.token' } }, ApiService, SocketService ] }); service = TestBed.inject(UserService); }); it('should be created', () => { expect(service).toBeTruthy(); }); });
注:自动生成的模拟类为空,若后续测试需要调用服务方法,需手动补充模拟实现。
内容的提问来源于stack exchange,提问作者Enrico Viappiani
相关产品推荐
相关产品推荐

