Angular Jasmine独立测试:测试ViewChild入口组件中的方法
Angular测试:解决ViewChild获取的ViewContainerRef无法Spy的问题
报错could not find an object to spy upon for createComponent()的核心原因是:测试环境中component.entry(即@ViewChild获取的ViewContainerRef)未被初始化,处于undefined状态,导致无法创建Spy。以下是两种可行的解决方案:
方案1:手动Mock ViewContainerRef
直接给组件的entry属性赋值Mock对象,模拟createComponent方法的行为,无需依赖模板渲染:
it("Test ViewChild", () => { // 1. 构建Mock的ComponentRef和ViewContainerRef const mockComponentRef = { instance: { data: null } }; const mockViewContainerRef = { createComponent: jasmine.createSpy('createComponent').and.returnValue(mockComponentRef) }; // 2. 替换组件的entry为Mock对象 component.entry = mockViewContainerRef as unknown as ViewContainerRef; // 3. 执行测试方法 const testData = { component: {}, inputs: { id: 1, name: 'test' } }; component.showComp(testData); // 4. 断言验证 expect(mockViewContainerRef.createComponent).toHaveBeenCalled(); expect(mockComponentRef.instance.data).toEqual(testData.inputs); });
方案2:依赖模板渲染初始化ViewChild
如果需要验证真实模板逻辑,需确保测试时模板被编译,且#template标记的元素存在(比如模板中有<ng-template #template></ng-template>):
步骤1:配置TestBed并触发变更检测
beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [TestModalComponent], providers: [ { provide: NgbActiveModal, useValue: { close: jasmine.createSpy('close') } }, { provide: UtilsService, useValue: { eventEmitter: new EventEmitter() } } ], schemas: [NO_ERRORS_SCHEMA] // 忽略模板中未知组件/指令的报错 }).compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(TestModalComponent); component = fixture.componentInstance; fixture.detectChanges(); // 触发变更检测,初始化ViewChild });
步骤2:编写测试用例
it("Test ViewChild", () => { // 此时entry已通过模板渲染初始化 spyOn(component.entry, "createComponent").and.returnValue({ instance: { data: null } }); const testData = { component: {}, inputs: { id: 1, name: 'test' } }; component.showComp(testData); expect(component.entry.createComponent).toHaveBeenCalled(); });
额外注意事项
组件代码中showComp方法的componentFactory变量未定义,实际运行会报错。测试时可通过以下方式处理:
- 在Mock的
createComponent中忽略参数验证,使用callFake直接返回预设的componentRef - 额外Mock
ComponentFactoryResolver,提供有效的组件工厂对象
内容的提问来源于stack exchange,提问作者Ivan Martin Blanco
相关产品推荐
相关产品推荐

