如何测试带有服务依赖与构造参数的Angular普通类?
如何测试带有服务依赖和独立构造参数的Angular普通类
问题背景
测试普通类MyClass时,参照组件测试方案配置TestBed后出现错误:
Unexpected value 'MyClass' imported by the module 'DynamicTestModule'. Please add a @NgModule annotation.
相关代码:
my-service.service.ts
@Injectable({ providedIn: 'root', }) export class MyService { ... }
my-class.ts
import { inject } from '@angular/core'; import { MyService } from './my-service.service'; export class MyClass { private _myService: MyService = inject(MyService); private _name: string; constructor(name: string) { this._name = name; } }
解决方案
普通类并非Angular的组件/指令/管道,不能添加到TestBed的declarations或imports配置中。需利用Angular的注入上下文来创建类实例,同时处理服务依赖。
方法一:使用TestBed.runInInjectionContext创建实例(推荐)
通过TestBed配置依赖,再在注入上下文内创建类实例,确保inject()能正常获取服务:
import { TestBed } from '@angular/core/testing'; import { MyService } from './my-service.service'; import { MyClass } from './my-class'; describe('MyClass', () => { let myServiceSpy: jasmine.SpyObj<MyService>; beforeEach(() => { // 创建MyService的Spy对象,用于模拟服务行为 myServiceSpy = jasmine.createSpyObj('MyService', ['yourMethodName']); // 配置TestBed,提供Mock服务替代真实服务 TestBed.configureTestingModule({ providers: [ { provide: MyService, useValue: myServiceSpy } ] }); }); it('should initialize with correct name and injected service', () => { // 在Angular注入上下文内创建MyClass实例 const instance = TestBed.runInInjectionContext(() => { return new MyClass('test-user'); }); expect(instance).toBeTruthy(); // 验证构造参数是否生效 expect(instance['_name']).toBe('test-user'); // 验证服务是否被正确注入 expect(instance['_myService']).toBe(myServiceSpy); }); });
方法二:直接注入服务后创建实例
若无需复杂Mock,可直接从TestBed获取服务实例,再在注入上下文内创建类:
import { TestBed } from '@angular/core/testing'; import { MyService } from './my-service.service'; import { MyClass } from './my-class'; describe('MyClass', () => { let myService: MyService; beforeEach(() => { TestBed.configureTestingModule({}); // 获取真实的MyService实例(或替换为Mock) myService = TestBed.inject(MyService); }); it('should work with real service', () => { const instance = TestBed.runInInjectionContext(() => new MyClass('test-name')); expect(instance['_name']).toBe('test-name'); // 可调用服务方法验证交互 // myService.someMethod(); // expect(...).toBe(...); }); });
错误原因说明
之前的配置错误将普通类MyClass添加到了TestBed的imports或declarations中,而这些配置项仅支持Angular的模块、组件、指令、管道类,普通类无法被识别,因此抛出@NgModule相关错误。
内容的提问来源于stack exchange,提问作者user9506231
相关产品推荐
相关产品推荐

