如何使用`entryComponents`对组件进行浅层测试?

时间:2017-01-17 05:13:18

标签: angular

例如,假设您有以下组件:

import { Another } from "./Another";
@Component({
    entryComponents: [
        Another
    ]
})
export class App {}

即使使用NO_ERRORS_SCHEMA,我仍然必须将Another作为测试声明的一部分包含在内:

import { ComponentFixture, TestBed } from "@angular/core/testing";
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { App } from "./App";
import { Another } from "./Another";

describe("App", () => {
  let comp: App;
  let fixture: ComponentFixture<App>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [ App, Another ],
      schemas: [ NO_ERRORS_SCHEMA ]
    });
    fixture = TestBed.createComponent(App);
    comp = fixture.componentInstance;
  });

  it("can load instance", () => {
    expect(comp).toBeTruthy();
  });

});

5 个答案:

答案 0 :(得分:10)

他们计划将EntryComponents添加到测试模块界面。请参阅问题:https://github.com/angular/angular/issues/10760

有关当前的解决方法,请参阅Angular材质库,请参阅https://github.com/angular/material2/blob/master/src/lib/dialog/dialog.spec.ts#L479

基本上,他们动态创建一个真实的模块,然后导入它进行测试。

// Create a real (non-test) NgModule as a workaround for
// https://github.com/angular/angular/issues/10760
const TEST_DIRECTIVES = [
  ComponentWithChildViewContainer,
  PizzaMsg,
  DirectiveWithViewContainer,
  ContentElementDialog
];

@NgModule({
  imports: [MdDialogModule],
  exports: TEST_DIRECTIVES,
  declarations: TEST_DIRECTIVES,
  entryComponents: [ComponentWithChildViewContainer, PizzaMsg, ContentElementDialog],
})
class DialogTestModule { }

现在您可以使用DialogTestModule

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [MdDialogModule.forRoot(), DialogTestModule]
      ...

答案 1 :(得分:4)

我的解决方案基于@kampsj解决方案,但我认为更清洁。

layoutManager = GridLayoutManager(context, spanCount, LinearLayoutManager.VERTICAL, false) 创建一个动态模块。因此,我们可以使用具有TestBed(无新功能)的模块。我的不同之处在于我没有创建一个testModule 我只是导入了这个组件所属的模块,并且更加清晰,因为你没有&#39;需要添加其他任何东西(服务,其他组件等。)。这应该意味着entryComponents是否有效,那么ng serve应该(至少从创建组件的角度来看)。

假设我们有以下结构:

ng test

componentThatCreateDynamicsComponents.component.spec.ts app ├--- app.module.ts ├--- app.component.ts ├--- ... ├--- SomeModule2 | ├--- somemodule2.module.ts | ├--- componentThatCreateDynamicsComponents | ├--- componentThatCreateDynamicsComponents.component.ts | ├--- componentThatCreateDynamicsComponents.html | ├--- componentThatCreateDynamicsComponents.component.spec.ts | ├--- someCOmponent | ├--- someCOmponent.component.ts | ├--- someCOmponent.html | ├--- someCOmponent.component.spec.ts 应从somemodule2.module.ts导入TestBed。如果您不将项目拆分为模块,则应该是您拥有的唯一模块。

您是否拥有在该测试中不会使用的组件,但这并不重要,因为它只是测试。当您更改测试模块时,您将获得灵活性。

答案 2 :(得分:0)

就我而言,仅将DialogComponent添加到声明中就足够了。

答案 3 :(得分:0)

我能够使用间谍来覆盖默认的附加行为:

it('openSearch calls to open the search overlay', () => {
    component.searchOverlayRef.hasAttached = () => false;
    spyOn(component.searchOverlayRef, 'attach').and.returnValue({
      instance: {dragStart: empty()} 
    });
    component.openSearch()
    expect(component.searchOverlayRef.attach).toHaveBeenCalled();
});

自从我测试实现以来,这并不是最好的测试,但是直到编写e2e测试来测试UI行为时,它才有效。

答案 4 :(得分:0)

您也可以尝试

从'@ angular / platform-b​​rowser-dynamic / testing'导入{BrowserDynamicTestingModule};

TestBed.configureTestingModule({
  declarations: [ MyDynamicComponent ],
}).overrideModule(BrowserDynamicTestingModule, {
  set: {
    entryComponents: [ MyDynamicComponent ],
  }
});