如何在角度7业力测试中测试组件是否动态加载?

时间:2019-01-04 06:49:00

标签: angular karma-jasmine

我制作了一个组件,在其中动态加载另一个在ng serve上运行良好的组件。以下是用于动态加载组件的代码。

import { Component, OnInit, ViewChild, ComponentFactoryResolver, Type, Input} from '@angular/core';
import { AddComponentDirective } from '../add-component.directive';
import { DynamicComponent } from '../dynamic/dynamic.component';
import { ComponentData } from '../component-data';
import { ComponentItem } from '../component-item';

  export class DynamicLoaderComponent implements OnInit {
      @ViewChild (AddComponentDirective) adhost : AddComponentDirective;

      constructor(private componentFactoryResolver : ComponentFactoryResolver) { }

      ngOnInit() {
          this.loadComponent(DynamicComponent,message,this.adhost);
      }

      loadComponent(comp, message, host){
          let adItem = new ComponentItem(comp,{msg: message});
          let componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component);
          let viewContainerRef = host.viewContainer;
          let componentRef = viewContainerRef.createComponent(componentFactory);
      (<ComponentData>componentRef.instance).data = adItem.data;
    }
 }

但是在使用角度业力测试进行测试时,我们面临类型错误,即

  

TypeError:this.componentFactoryResolver.resolveComponentFactory不是函数

下面是我正在测试的 spec.ts 文件。

import { async, ComponentFixture, TestBed ,getTestBed,inject} from '@angular/core/testing';
import {ComponentFactoryResolver,ViewChild,DebugElement} from '@angular/core';
import { AddComponentDirective } from '../add-component.directive';
import { DynamicComponent } from '../dynamic/dynamic.component';
import { DynamicLoaderComponent } from './dynamic-loader.component';
import { BrowserDynamicTestingModule } from "@angular/platform-browser-dynamic/testing";
import { ComponentData } from "../component-data";

describe('DynamicLoaderComponent', () => {
  let component: DynamicLoaderComponent;
  let fixture: ComponentFixture<DynamicLoaderComponent>;
  let injector: TestBed;
  let componentFactoryResolver : ComponentFactoryResolver ;
  let debugElement: DebugElement

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ DynamicLoaderComponent,AddComponentDirective ,DynamicComponent],
      providers:[DynamicLoaderComponent,ComponentFactoryResolver]
    })
    .compileComponents();

    TestBed.overrideModule(BrowserDynamicTestingModule, {
      set: {
        entryComponents: [DynamicComponent]
      }
    });

  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(DynamicLoaderComponent);
    component = fixture.componentInstance;
    componentFactoryResolver =  fixture.debugElement.injector.get(ComponentFactoryResolver);
    fixture.detectChanges();
  });  

  it('should create the DynamicLoaderComponent',inject([DynamicLoaderComponent], (component : DynamicLoaderComponent) => {
    expect(component).toBeTruthy();
  }));

});

An image of the error of the test file on the browser is attached. Click to view

您能帮我解决这个问题,以便我进一步进行动态组件的测试吗?

1 个答案:

答案 0 :(得分:2)

您需要进行一些更改以修复这些错误:

1)从TestBed配置中删除providers

TestBed.configureTestingModule({
  declarations: [ DynamicLoaderComponent,AddComponentDirective ,DynamicComponent],
  providers:[DynamicLoaderComponent,ComponentFactoryResolver] <== remove this line
})

2)您不需要从DI中获取组件,

所以替换

it('should create the DynamicLoaderComponent', inject([DynamicLoaderComponent], (component : DynamicLoaderComponent) => {
  expect(component).toBeTruthy();
}));

具有:

it('should create the DynamicLoaderComponent', () => {
  expect(component).toBeTruthy();
});

3)仅在非CLI环境中运行测试时才需要compileComponents()调用。

来自Angular doc

  

调用compileComponents()将当前TestBed实例关闭为   进一步配置。您无法再调用任何TestBed配置   方法,而不是configureTestingModule()或任何替代方法...   方法。如果尝试,TestBed会引发错误。

这意味着您的TestBed.overrideModule通话不会有任何效果,也不会找到DynamicComponent的工厂。

因此删除.compileComponents();

TestBed.configureTestingModule({
  declarations: [ DynamicLoaderComponent,AddComponentDirective ,DynamicComponent],
  providers:[DynamicLoaderComponent,ComponentFactoryResolver]
})
.compileComponents(); <==== remove this

如果您使用的是非angular-cli环境,则可以在覆盖模块之后调用它:

TestBed.overrideModule(BrowserDynamicTestingModule, {
  set: {
    entryComponents: [DynamicComponent]
  }
});

TestBed.compileComponents(); <== this line

我在上面进行了所有更改之后,应该正确执行测试。

Plunker Example