角度指令ViewContainerRef测试模型

时间:2019-06-30 21:10:03

标签: angular jasmine

给出用于Dynamic Component Loading且注入了ViewContainerRef的指令:

import { Directive, ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[fooHost]'
})
export class FooDirective {
  constructor(public viewContainerRef: ViewContainerRef) {}
}

如何在单元测试中注入ViewContainerRef的实例或模拟:

import { FooDirective } from './foo.directive';

describe('FooDirective', () => {
  it('should create an instance', () => {
    const directive = new FooDirective();
    expect(directive).toBeTruthy();
  });
});

此最基本的测试由于以下错误而失败:

  

未提供'viewContainerRef'的参数。

testing guide并未涵盖这一点,也似乎没有专门用于创建ViewContainerRef实例的测试模块。

这是简单的吗,例如用@Component创建存根TestBed.createComponent并将夹具或组件实例作为ViewContainerRef传递?

import { FooDirective } from './foo.directive';
import { ViewContainerRef, Component } from '@angular/core';
import { TestBed, async } from '@angular/core/testing';

@Component({ selector: 'app-stub', template: '' })
class StubComponent {}

describe('LightboxDirective', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({ declarations: [StubComponent] }).compileComponents();
  }));

  it('should create an instance', () => {
    const fixture = TestBed.createComponent(StubComponent);
    const component = fixture.debugElement.componentInstance;

    const directive = new FooDirective(component);
    expect(directive).toBeTruthy();
  });
});

如果是这种情况,应该以{{1​​}},ViewContainerReffixture.debugElement.componentInstance或其他形式传递什么?

谢谢!

1 个答案:

答案 0 :(得分:4)

ViewContainerRef是从@angular/core导入的抽象类。由于它是抽象类,因此无法直接实例化。但是,在测试类中,您可以简单地创建一个extends ViewContainerRef的新类,并实现所有必需的方法。然后,您可以简单地实例化TestViewContainerRef的新实例,并将其传递到测试/规范中的FooDirective构造函数中。因此:

// create the test class
class TestViewContainerRef extends ViewContainerRef {
  get element(): import("@angular/core").ElementRef<any> {
    throw new Error("Method not implemented.");
  }
  get injector(): import("@angular/core").Injector {
    throw new Error("Method not implemented.");
  }
  get parentInjector(): import("@angular/core").Injector {
    throw new Error("Method not implemented.");
  }
  clear(): void {
    throw new Error("Method not implemented.");
  }
  get(index: number): import("@angular/core").ViewRef {
    throw new Error("Method not implemented.");
  }
  get length(): number {
    throw new Error("Method not implemented.");
  }
  createEmbeddedView<C>(templateRef: import("@angular/core").TemplateRef<C>, context?: C, index?: number): import("@angular/core").EmbeddedViewRef<C> {
    throw new Error("Method not implemented.");
  }
  createComponent<C>(componentFactory: import("@angular/core").ComponentFactory<C>, index?: number, injector?: import("@angular/core").Injector, projectableNodes?: any[][], ngModule?: import("@angular/core").NgModuleRef<any>): import("@angular/core").ComponentRef<C> {
    throw new Error("Method not implemented.");
  }
  insert(viewRef: import("@angular/core").ViewRef, index?: number): import("@angular/core").ViewRef {
    throw new Error("Method not implemented.");
  }
  move(viewRef: import("@angular/core").ViewRef, currentIndex: number): import("@angular/core").ViewRef {
    throw new Error("Method not implemented.");
  }
  indexOf(viewRef: import("@angular/core").ViewRef): number {
    throw new Error("Method not implemented.");
  }
  remove(index?: number): void {
    throw new Error("Method not implemented.");
  }
  detach(index?: number): import("@angular/core").ViewRef {
    throw new Error("Method not implemented.");
  }

}

提示:我在Mac上使用VS Code。当我创建类存根class TestViewContainerRef extends ViewContainerRef { }时,代码为我提供了一个非常有用的代码提示,以实现所有抽象方法。我用它来自动生成上面的代码。其他IDE可能会提供类似的功能,以帮助过程顺利进行。您可能可以在此处复制/粘贴代码以在测试/规范类中使用。但是,Angular可以随时选择更改ViewContainerRef抽象类的接口,因此,如果您确实在上面复制了此代码,请注意,这样做后果自负。

以下是我如何使用它来使Angular测试通过的示例:

import { ModalHostDirective } from './modal-host.directive';
import { ViewContainerRef } from '@angular/core';

class TestViewContainerRef extends ViewContainerRef {
  get element(): import("@angular/core").ElementRef<any> {
    throw new Error("Method not implemented.");
  }
  get injector(): import("@angular/core").Injector {
    throw new Error("Method not implemented.");
  }
  get parentInjector(): import("@angular/core").Injector {
    throw new Error("Method not implemented.");
  }
  clear(): void {
    throw new Error("Method not implemented.");
  }
  get(index: number): import("@angular/core").ViewRef {
    throw new Error("Method not implemented.");
  }
  get length(): number {
    throw new Error("Method not implemented.");
  }
  createEmbeddedView<C>(templateRef: import("@angular/core").TemplateRef<C>, context?: C, index?: number): import("@angular/core").EmbeddedViewRef<C> {
    throw new Error("Method not implemented.");
  }
  createComponent<C>(componentFactory: import("@angular/core").ComponentFactory<C>, index?: number, injector?: import("@angular/core").Injector, projectableNodes?: any[][], ngModule?: import("@angular/core").NgModuleRef<any>): import("@angular/core").ComponentRef<C> {
    throw new Error("Method not implemented.");
  }
  insert(viewRef: import("@angular/core").ViewRef, index?: number): import("@angular/core").ViewRef {
    throw new Error("Method not implemented.");
  }
  move(viewRef: import("@angular/core").ViewRef, currentIndex: number): import("@angular/core").ViewRef {
    throw new Error("Method not implemented.");
  }
  indexOf(viewRef: import("@angular/core").ViewRef): number {
    throw new Error("Method not implemented.");
  }
  remove(index?: number): void {
    throw new Error("Method not implemented.");
  }
  detach(index?: number): import("@angular/core").ViewRef {
    throw new Error("Method not implemented.");
  }

}

describe('ModalHostDirective', () => {
  it('should create an instance', () => {
    const directive = new ModalHostDirective(new TestViewContainerRef());
    expect(directive).toBeTruthy();
  });
});

免责声明:就实际针对此TestViewContainerRef编写测试而言,...我将其留给大家。但这至少满足ng test

干杯!