Angular测试中Mock接口遇类型用作值报错,求解决办法
Angular测试中Mock IAppConfiguration接口的解决方案
报错原因
你遇到的两个错误本质是同一个问题:
- TypeScript的接口仅存在于编译阶段,运行时不会被编译成JS对象,所以
IAppConfiguration不能直接作为依赖注入(DI)的令牌使用。 AppConfigFake是接口而非可实例化的类,useClass参数要求传入一个能通过new创建实例的类,因此会提示“仅指类型,被用作值”。
可行解决方案
方案1:用类实现接口(适合需要模拟类行为的场景)
把AppConfigFake从接口改成类,实现IAppConfiguration的所有属性,再用useClass提供这个类:
fdescribe('MyDetails', () => { class ConfigServiceFake extends ConfigurationService {} // 将接口改为类,实现IAppConfiguration的所有属性 class AppConfigFake implements IAppConfiguration { recall: string = '测试召回值'; customer: string = '测试客户值'; // 补充IAppConfiguration中定义的其他所有属性,按需设置测试用默认值 } beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [MyDetails], imports: [HttpClientTestingModule, RouterTestingModule], providers: [ { provide: ConfigService, useClass: ConfigServiceFake }, { provide: IAppConfiguration, useClass: AppConfigFake } ] }).compileComponents(); }); });
方案2:直接用useValue提供模拟对象(适合静态配置场景)
如果IAppConfiguration只是静态配置对象,不需要类的行为,直接用useValue传入符合接口结构的对象更简单:
fdescribe('MyDetails', () => { class ConfigServiceFake extends ConfigurationService {} beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [MyDetails], imports: [HttpClientTestingModule, RouterTestingModule], providers: [ { provide: ConfigService, useClass: ConfigServiceFake }, { provide: IAppConfiguration, useValue: { recall: '测试召回值', customer: '测试客户值', // 必须包含IAppConfiguration定义的所有属性 } } ] }).compileComponents(); }); });
方案3:使用InjectionToken(官方推荐的规范做法)
由于TypeScript接口不能作为DI令牌,Angular官方建议用InjectionToken来标识接口类型的依赖:
- 在业务代码中定义令牌:
// 配置相关文件中 import { InjectionToken } from '@angular/core'; export const APP_CONFIG = new InjectionToken<IAppConfiguration>('应用配置');
- 业务服务中通过令牌注入:
import { Injectable, Inject } from '@angular/core'; @Injectable() export class YourBusinessService { constructor(@Inject(APP_CONFIG) private appConfig: IAppConfiguration) {} }
- 测试中Mock令牌对应的依赖:
fdescribe('MyDetails', () => { class ConfigServiceFake extends ConfigurationService {} beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [MyDetails], imports: [HttpClientTestingModule, RouterTestingModule], providers: [ { provide: ConfigService, useClass: ConfigServiceFake }, { provide: APP_CONFIG, useValue: { recall: '测试召回值', customer: '测试客户值', // 补充IAppConfiguration的所有属性 } } ] }).compileComponents(); }); });
内容的提问来源于stack exchange,提问作者user1015388
相关产品推荐
相关产品推荐

