测试中如何获取传递给组件的父Injector实例
问题描述
组件中通过构造函数注入私有Injector:
constructor( private injector: Injector, ) {}
接着用该实例作为父注入器创建新Injector,用于打开Material对话框:
const dialogRef = this.dialog.open(CoolDialogComponent, { data: { /* 自定义数据 */ }, injector: Injector.create({ providers: [/* 自定义提供者列表 */], parent: this.injector, }), });
测试环节需要验证对话框打开时的参数是否正确,特别是要拿到组件中注入的精确Injector实例作为父注入器来匹配:
expect(dialogSpy.open).toHaveBeenCalledWith(CoolDialogComponent, { data: {}, injector: Injector.create({ providers: [], parent: /* 需要拿到组件中注入的那个Injector实例 */, }), });
尝试过fixture.componentRef.injector、fixture.debugElement.injector、TestBed.inject(Injector)等方法,但都无法获取目标实例。目前只能把组件的injector改成public来获取,希望找到更合理的方案。
TL;DR
测试时如何获取传递给组件的精确Injector实例?
解决方案
1. 自定义提供者捕获Injector实例
在测试配置阶段,通过自定义工厂提供者捕获组件将注入的Injector实例:
let componentInjector: Injector; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [YourComponent], providers: [ { provide: Injector, useFactory: (injector: Injector) => { componentInjector = injector; return injector; }, deps: [Injector] } ] }).compileComponents(); });
组件初始化后,componentInjector就是构造函数中注入的那个私有实例,测试时直接用它做匹配即可:
expect(dialogSpy.open).toHaveBeenCalledWith(CoolDialogComponent, { data: {}, injector: Injector.create({ providers: [], parent: componentInjector, }), });
2. 提前注入测试用Injector实例
直接在TestBed中提供一个可控的Injector实例,让组件构造函数注入这个实例:
let testInjector: Injector; beforeEach(async () => { // 创建或获取测试用Injector实例 testInjector = TestBed.inject(Injector); await TestBed.configureTestingModule({ declarations: [YourComponent], providers: [ { provide: Injector, useValue: testInjector } ] }).compileComponents(); });
测试时直接使用testInjector作为父注入器参数,就能精确匹配调用。
3. 非精确匹配(可选)
如果不需要严格验证实例本身,只需要确认参数结构正确,可以用部分匹配语法:
// Jasmine 写法 expect(dialogSpy.open).toHaveBeenCalledWith(CoolDialogComponent, jasmine.objectContaining({ data: {}, injector: jasmine.any(Injector) })); // Jest 写法 expect(dialogSpy.open).toHaveBeenCalledWith(CoolDialogComponent, expect.objectContaining({ data: {}, injector: expect.any(Injector) }));
这种方式不需要获取精确实例,适合只验证逻辑流程的场景。
内容的提问来源于stack exchange,提问作者Elias
相关产品推荐
相关产品推荐

