Angular 19独立组件中非根注入服务的Karma Jasmine模拟问题
解决Angular独立组件内服务无法在Karma测试中模拟的问题
为啥你写的模拟不生效?因为组件自身的providers数组里声明的服务,优先级高于测试模块的providers配置——组件的注入器层级比模块注入器高,会优先用自己提供的实例,所以测试模块里的模拟服务根本没被用上。
直接有效的解决方案:覆盖组件的providers配置
修改测试代码,用TestBed.overrideComponent替换组件内原有的TestService为模拟实例:
describe('AppComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ imports: [AppComponent] }) // 关键步骤:覆盖组件的providers元数据 .overrideComponent(AppComponent, { set: { providers: [{ provide: TestService, useValue: { getData: () => ('mocked data') } }] } }) .compileComponents(); }); it('should create the app and return mocked data', () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; expect(app).toBeTruthy(); expect(app.service.getData()).toBe('mocked data'); // 现在会符合预期 }); });
原理说明
独立组件的providers属于组件自己的注入器上下文,测试模块的providers是模块级别的依赖配置。Angular的注入器查找规则是先找自身上下文,再往上找父级注入器,所以组件自己的服务实例会被优先使用。overrideComponent就是专门用来在测试时修改组件的元数据,直接替换掉组件原本提供的服务,这样就能让组件用我们的模拟实例。
另一种可选方式(适合简单场景)
如果你的组件是用inject()获取服务,也可以通过TestBed.runInInjectionContext手动注入模拟服务来实例化组件:
it('should use mocked service via injection context', () => { const mockTestService = { getData: () => 'mocked data' }; let app: AppComponent; TestBed.runInInjectionContext(() => { TestBed.overrideProvider(TestService, { useValue: mockTestService }); app = new AppComponent(); }); expect(app.service.getData()).toBe('mocked data'); });
不过第一种方案更贴合常规的组件测试流程,推荐优先使用。
内容的提问来源于stack exchange,提问作者Abdullah El-Kindy
相关产品推荐
相关产品推荐

