【问题标题】:Angular / Jasmine: No provider for Overlay! Also how to test a material dialogAngular / Jasmine:没有覆盖提供者!还有如何测试材质对话框
【发布时间】:2020-09-26 23:38:25
【问题描述】:

我正在尝试测试一个有角度的材质对话框,具体来说,我想测试它是否在对话框关闭时修改了路线。为此,我不想模拟/存根对话框(我不认为?),因为我希望它运行执行重新路由的实际 .subscribe 方法。

在我的实际对话框中出现两个错误:

this.dialogRef.afterClosed is not a function

login-dialog-component.spec.ts

describe('LoginDialogComponent', () => {
  let component: LoginDialogComponent;
  let fixture: ComponentFixture<LoginDialogComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [LoginDialogComponent],
      imports: [
        RouterTestingModule.withRoutes([]),
        MatDialogModule
      ],
      providers: [
        {provide: MatDialog},
        {provide: MAT_DIALOG_DATA, useValue: {}},
        {provide: MatDialogRef, useValue: {}},
      ]
    })
      .compileComponents();
  }));

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

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

我遇到的第二个错误是打开我的对话框的组件的测试。它报告:

NullInjectorError: R3InjectorError(DynamicTestModule)[MatDialog -> Overlay -> Overlay]: 
  NullInjectorError: No provider for Overlay!

打开我的对话框的组件测试:login.component.spec.ts

describe('LoginComponent', () => {
  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ LoginComponent ],
      providers: [
        { provide: MatDialog },
        { provide: MAT_DIALOG_DATA, useValue: {} },
        { provide: MatDialogRef, useValue: {}}
      ]
    })
    .compileComponents();
  }));

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

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

LoginComponent 本身并不真正需要任何测试,但如上所述,它给了我“No provider for overlay”,大概是因为构造函数是:

 constructor(
    private dialog: MatDialog
  ) { }

LoginComponent 然后打开 LoginDialog。

我希望在 LoginDialog 中测试的代码是:

 ngOnInit(): void {
    this.dialogRef.afterClosed().subscribe(_ =>
      this.router.navigate(['', {outlets: {login: null}}])
    );
  }

我想确保当对话框关闭时路由器真正导航离开。

所以我的问题是

  1. 如何将真实的 dialogRef 传递给 LoginDialog 的构造函数?
  2. 如何摆脱 No provider for Overlay 错误?

顺便说一句,如果我改变了

{ provide: MatDialogRef, useValue {})

到:

{ provide: MatDialogRef }

(所以我大概是在尝试传递一个实际的 MatDialogRef)

错误变化自

this.dialogRef.afterClosed is not a function

到:

Can't resolve all parameters for MatDialogRef: (?, ?).

谢谢。

【问题讨论】:

    标签: angular jasmine


    【解决方案1】:

    试试:

    login-dialog-component.spec.ts 中,删除整个providers 数组,因为我们不应该嘲笑MatDialog 的内部工作,而是在imports 中保留MatDialogModule

    login.component.spec.ts 中,将MatDialogModule 添加到TestBed.configureTestingModuleimports 数组中,并如前所述删除providers 数组。

    【讨论】:

    • 1) 这给了我“MatDialogRef 没有提供者”。我在github.com/angular/components/issues/… 上发现似乎在测试期间无法注入 MatDialogRef,因此解决方案是使用模拟。
    • stackoverflow.com/questions/48703365/… 抱歉,请查看最后 2 个答案。
    • 2) 谢谢,这似乎已经解决了 LoginComponent 的问题。我认为要解决另一个问题,我将不得不使用模拟,如果无法注入真正的 MatDialogRef,我将无法测试路由器代码。我可能会接受你的回答。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-21
    • 2017-12-22
    • 2019-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多