单元测试Angular 5 - 期望关闭Dialog

时间:2018-02-14 08:37:12

标签: unit-testing angular-material2 angular5

我有一个组件(它是一个MatDialog组件),其中一个函数只是保存一些日期并在结尾(对话框)关闭它,只需调用“this.dialogRef.close(true);” 。到现在为止还挺好。 问题在于单元测试。当我尝试测试此函数时,Karma会抛出错误“TypeError:this.dialogRef.close不是函数”。我想它不会识别在对话框中调用的函数close,因为我必须忘记在我的spec.ts文件中以某种方式启动此dialogRef,但我不知道如何继续,考虑到事实并非如此关于在spec.ts中配置Material 2组件的网上有很多材料。我的问题是:如何让这个测试通过单元测试来识别这个dialogRef.close()函数。

下面的一些示例代码: timeRangeDialogComponent.ts

import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';

export class TimeRangeDialogComponent implements OnInit, OnDestroy {

 constructor(public dialogRef: MatDialogRef<TimeRangeDialogComponent>,
           @Inject(MAT_DIALOG_DATA) public data: any) {
 }

 saveCustomTimeRange(): void {
   this.dialogRef.close(true);
 }
}

TimeRangeDialogComponent.spec.ts

beforeEach(async(() => {
  TestBed.configureTestingModule({
    declarations: [ TimeRangeDialogComponent ],
    imports: [ FormsModule, MaterialModule, MatDatepickerModule ],
    providers: [
      { provide: MatDialogRef, useValue: {} },
      { provide: MAT_DIALOG_DATA, useValue: [] } ]
  })
    .compileComponents();
}));

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

it('should call the function to close the dialog', () => {
  component.saveCustomTimeRange();
  expect(component.dialogRef.close()).toHaveBeenCalled();
});

抛出错误:TypeError:this.dialogRef.close不是函数

我事先感谢你的帮助。

4 个答案:

答案 0 :(得分:3)

修复它的一种方法是提供具有close方法的对话框类的模拟,而不是仅在提供者数组中提供空对象。类似的东西:

// mock object with close method
const dialogMock = {
    close: () => { }
};

beforeEach(async(() => {
  TestBed.configureTestingModule({
    declarations: [ TimeRangeDialogComponent ],
    imports: [ FormsModule, MaterialModule, MatDatepickerModule ],
    providers: [
      { provide: MatDialogRef, useValue: dialogMock },
      { provide: MAT_DIALOG_DATA, useValue: [] } ]
  })
    .compileComponents();
}));

此处的close方法实际上并没有做任何事情,但您可以检查它是否至少被调用过。

答案 1 :(得分:0)

这里的问题是您没有想要进行的间谍设置​​。

spyOn(component.dialogRef, 'close');

答案 2 :(得分:0)

这是ngZone的一个开放式错误和解决方案。尝试这样。

export class ErrorDialogService {
  constructor(public dialog: MatDialog, private ngZone: NgZone) {
  }

  openDialog(dialogData: DialogData): any {
    const dialogConfig = new MatDialogConfig();
    dialogConfig.disableClose = true;
    dialogConfig.autoFocus = true;
    dialogConfig.data = dialogData;
    let dialogRef;
    this.ngZone.run(() => {
      dialogRef = this.dialog.open(ErrorDialogComponent, dialogConfig);

    });
    dialogRef.afterClosed().subscribe(result => {
      console.log('The dialog was closed');
    });
  }
}

和对话框

export class ErrorDialogComponent implements OnInit {

  title = '';
  data: DialogData;

  constructor(private dialogRef: MatDialogRef<ErrorDialogComponent>,
              @Inject(MAT_DIALOG_DATA) dialogData: DialogData) {
    this.title = 'StarsWriters-Interceptor';
    this.data = dialogData;
  }

  ngOnInit(): void {
  }

  close() {
    console.log('CLOSE CLICKED'); // works
    this.dialogRef.close(true);   // Before running ErrorDialogService.openDialog without ngZone.run Fired but nothing happens. 
  }
}

答案 3 :(得分:0)

只需在close方法中添加间谍即可完成

该问题在期望部分中也包含错误,它正在调用close函数,它应该是引用[ close 而不是 close()]。< / p>

it('should call the function to close the dialog', () => {
  spyOn(component.dialogRef, "close");
  component.saveCustomTimeRange();
  expect(component.dialogRef.close).toHaveBeenCalled();
});