【问题标题】:Angular Unit Test Error: No component factory found for Component. Did you add it to @NgModule.entryComponentsAngular 单元测试错误:找不到组件的组件工厂。您是否将其添加到 @NgModule.entryComponents
【发布时间】:2019-07-25 14:13:19
【问题描述】:

我正在尝试自学如何使用 Angular 进行编码,但遇到了问题。我正在为自己创建一个应用程序,并且我刚刚实现了 Angular Material Dialog。我把它放在一个包装服务中,一切看起来都很好。所以在一个组件中,我调用 Wrapper Service 来引发这样的模式......

public assignInstrument(instrument: any): void {
    this.modalDialogWrapperService.openAssignmentWindow({
        product: 'instrument',
        type: instrument.type,
        serial: instrument.serial,
        id: instrument.id
  });
}

服务方法看起来像这样,注意我在模态窗口中传递了我希望提出的组件的名称

openAssignmentWindow(instrument) {
    const dialogRef = this.dialog.open(ChangeAssignmentComponent, {
        data: instrument,
        width: '693px',
        height: '498px'
        });
    dialogRef.afterClosed().subscribe(() => {});
    });
}

一切都很好!但作为一名优秀的开发人员,我应该编写单元测试......所以为了测试我的组件,我进行了以下测试(我已经包括了我如何模拟服务和其他一些代码来给测试文件留下印象)

let modalDialogWrapperServiceSpy: jasmine.SpyObj<ModalDialogWrapperService>;
    const mockModalDialogWrapperService = jasmine.createSpyObj('ModalDialogWrapperService', ['openAssignmentWindow']);
    mockModalDialogWrapperService.openAssignmentWindow.and.returnValue({});

TestBed.configureTestingModule({
    imports: [...],
    declarations: [...],
    providers: [{
      provide: ModalDialogWrapperService,
      useValue: mockModalDialogWrapperService
    }]
}).compileComponents();

beforeEach(() => {
    fixture = TestBed.createComponent(InstrumentsPageComponent);
    modalDialogWrapperServiceSpy = TestBed.get(ModalDialogWrapperService);
    component = fixture.componentInstance;
    fixture.detectChanges();
 })

describe('assignInstrument', () => {
  it('should call the Modal Dialog Service', () => {
    component.assignInstrument({});
    expect(modalDialogWrapperServiceSpy.openAssignmentWindow).toHaveBeenCalledTimes(1);
  });
});

这一项测试失败了!出现错误“错误:未找到 ChangeAssignmentComponent 的组件工厂。您是否将其添加到 @NgModule.entryComponents” - 这似乎很奇怪,因为在我的 app.module 文件中我在 entryComponents 和声明数组中声明了“ChangeAssignmentComponent”?我很困惑 - 有人知道我做错了什么吗?

【问题讨论】:

  • 您是否在规范中导入了module,其中您的组件为declared 并添加为entryComponents
  • 我的应用程序中只有一个模块,所以我没有在我的测试平台的导入数组中声明它,例如:imports: [MatTableModule, MatPaginatorModule, MatDialogModule, NoopAnimationsModule],

标签: angular unit-testing jasmine


【解决方案1】:

测试令人怀疑。

更严肃的,让我回答你。

在 Angular 中,您的组件由模块处理。当您使用 Material 对话框和零食时,您实际上使用了 CDK 的一个功能,称为Portal。这允许您动态创建组件。

但是当你这样做时,你必须将它们添加到你模块的entryComponents。你是在你的模块中做的,所以你也应该在你的测试中做。

语法是

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

【讨论】:

  • 当我添加上面的代码时,我得到了以下错误“失败:组件 ChangeAssignmentComponent 不是任何 NgModule 的一部分,或者该模块尚未导入到您的模块中。”
  • 您是否将上述组件添加到您的测试平台模块配置中?
  • 哦,我不这么认为,这会在声明数组中吗?
  • @NewToAngular 完全正确
  • 似乎已经解决了这个问题,但我的测试失败了“预期间谍 ModalDialogWrapperService.openAssignmentWindow 已被调用一次。它被调用了 0 次。”所以我还有更多需要解决的问题,但导入问题现已解决 - 谢谢
【解决方案2】:

有两个地方应该这样做......入口组件和声明处(在配置测试模块时)......

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

【讨论】:

  • 您的答案应该已被接受为该主题的答案。谢谢你对我有帮助。
【解决方案3】:

如果有人难以找到BrowserDynamicTestingModule,请改用BrowserModule

   TestBed
  .configureTestingModule(...)
  .overrideModule(BrowserModule, { set: { entryComponents: [YourComponent] } });

【讨论】:

  • 你可以像这样导入BrowserDynamicTestingModuleimport { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
猜你喜欢
  • 2018-04-09
  • 2019-11-06
  • 2019-01-30
  • 1970-01-01
  • 2018-05-06
  • 2019-09-05
  • 2017-09-25
  • 1970-01-01
相关资源
最近更新 更多