如何测试动态加载组件的 Angular (v11) 组件

发布于 2025-01-09 11:17:31 字数 2414 浏览 1 评论 0原文

在我的代码中,我遵循 Angular v11 指南,

@Directive({
  selector: '[stepHostContent]',
})
export class StepHostContentDirective {
  constructor(public viewContainerRef: ViewContainerRef) { }
}

@Component({
  selector: 'app-dialog-wizard',
  templateUrl: './dialog-wizard.component.html',
  styleUrls: ['./dialog-wizard.component.scss']
})
export class DialogWizardComponent implements OnInit, OnDestroy {

  @ViewChild(StepHostContentDirective, { static: true }) stepHostContent: StepHostContentDirective;

  constructor(
    public readonly dialog: MatDialogRef<DialogJobsWizardComponent>,
    @Inject(MAT_DIALOG_DATA) public readonly data: { theme: string, title: string },
    public readonly componentFactoryResolver: ComponentFactoryResolver
  ) { }
...
private loadStepContentComponent(componentToLoad: Type<any>): void {
   const componentFactory =  this.componentFactoryResolver.resolveComponentFactory(componentToLoad);
   const viewContainerRef = this.stepHostContent.viewContainerRef;
   viewContainerRef.clear();

   viewContainerRef.createComponent(componentFactory);
 }

我的单元测试

describe('DialogWizardComponent', () => {
  let component: DialogWizardComponent;
  let fixture: ComponentFixture<DialogWizardComponent>;
  let componentFactoryResolverSpy = jasmine.createSpyObj<ComponentFactoryResolver>('ComponentFactoryResolver', ['resolveComponentFactory'])
  
  beforeEach(async () => {
    componentFactoryResolverSpy = spyComponentFactoryResolverSpy();
    await TestBed.configureTestingModule({
      declarations: [ 
        DialogsWizardComponent,
        MockComponent(DialogBaseComponent),
        MockComponent(StepTestAComponent),
        MockComponent(StepTestBComponent),
        StepHostContentDirective
      ],
      providers: [
        { provide: MatDialogRef, useValue: { close: () => {} } },
        { provide: MAT_DIALOG_DATA, useValue: { theme: 'dark', title: 'Title' } },
        { provide: ComponentFactoryResolver, useValue: componentFactoryResolverSpy },
      ],
    })
    .compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(DialogWizardComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

错误显示

无法读取未定义的属性(读取'ngModule') 指向这一行viewContainerRef.createComponent(componentFactory);

In my code I'm following Angular v11 guide for that

@Directive({
  selector: '[stepHostContent]',
})
export class StepHostContentDirective {
  constructor(public viewContainerRef: ViewContainerRef) { }
}

@Component({
  selector: 'app-dialog-wizard',
  templateUrl: './dialog-wizard.component.html',
  styleUrls: ['./dialog-wizard.component.scss']
})
export class DialogWizardComponent implements OnInit, OnDestroy {

  @ViewChild(StepHostContentDirective, { static: true }) stepHostContent: StepHostContentDirective;

  constructor(
    public readonly dialog: MatDialogRef<DialogJobsWizardComponent>,
    @Inject(MAT_DIALOG_DATA) public readonly data: { theme: string, title: string },
    public readonly componentFactoryResolver: ComponentFactoryResolver
  ) { }
...
private loadStepContentComponent(componentToLoad: Type<any>): void {
   const componentFactory =  this.componentFactoryResolver.resolveComponentFactory(componentToLoad);
   const viewContainerRef = this.stepHostContent.viewContainerRef;
   viewContainerRef.clear();

   viewContainerRef.createComponent(componentFactory);
 }

My unit test

describe('DialogWizardComponent', () => {
  let component: DialogWizardComponent;
  let fixture: ComponentFixture<DialogWizardComponent>;
  let componentFactoryResolverSpy = jasmine.createSpyObj<ComponentFactoryResolver>('ComponentFactoryResolver', ['resolveComponentFactory'])
  
  beforeEach(async () => {
    componentFactoryResolverSpy = spyComponentFactoryResolverSpy();
    await TestBed.configureTestingModule({
      declarations: [ 
        DialogsWizardComponent,
        MockComponent(DialogBaseComponent),
        MockComponent(StepTestAComponent),
        MockComponent(StepTestBComponent),
        StepHostContentDirective
      ],
      providers: [
        { provide: MatDialogRef, useValue: { close: () => {} } },
        { provide: MAT_DIALOG_DATA, useValue: { theme: 'dark', title: 'Title' } },
        { provide: ComponentFactoryResolver, useValue: componentFactoryResolverSpy },
      ],
    })
    .compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(DialogWizardComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

the error says

Cannot read properties of undefined (reading 'ngModule')
pointing to this line viewContainerRef.createComponent(componentFactory);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

噩梦成真你也成魔 2025-01-16 11:17:31

您需要模拟 ViewContainerRef。

You need to mock ViewContainerRef.

https://angular.io/guide/testing-components-basics

苯莒 2025-01-16 11:17:31

我修复了它,从提供程序中删除了 ComponentFactoryResolver,并且它起作用了

I fixed it removing the ComponentFactoryResolver from providers, and it worked

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文