在Jasmine中对MatDialog进行单元测试时,无法读取未定义的属性'afterClosed'

时间:2019-02-19 13:48:31

标签: angular typescript dialog jasmine angular-material

我从业力茉莉花中收到以下错误:
TypeError: Cannot read property 'afterClosed' of undefined

我进行了认真的搜索,但在Stack Overflow或其他来源中找不到解决方案。

这是我在组件中打开MatDialog的方式:
(类似于documented

constructor(public dialog: MatDialog) {}

public openDialog(): void {
    const dialogReference: MatDialogRef<any, any> = this.dialog.open(myDialogComponent, {
        width: '1728px'
    });

    dialogReference.afterClosed().subscribe((result) => {
    });
}

这是我的单元测试配置:

beforeEach(async(() => {
    TestBed.configureTestingModule({
        declarations: [
            myRequestComponent
        ],
        imports: [
            MatDialogModule,
            ReactiveFormsModule
        ],
        providers: [
            { provide: MatDialog, useValue: {} },
        ],
        schemas: [CUSTOM_ELEMENTS_SCHEMA]
    }).compileComponents();
}));

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

这是我的单元测试:

it('openDialog() should open a dialog', () => {
    spyOn(component.dialog, 'open');

    component.openDialog();

    expect(component.dialog.open).toHaveBeenCalled();
});

我是否必须模拟MatDialog或MatDialogReference?

2 个答案:

答案 0 :(得分:2)

让我们逐步解决您的问题。

第一,通过注册

providers: [{ provide: MatDialog, useValue: {} }],

每当需要解决MatDialog时,您的测试台将注入一个没有任何行为的对象(例如,实例方法/成员)。

这并不是真正必要的,因为您正在将MatDialogModule导入到测试平台中,因此可以解决MatDialog的实例而没有问题。 但是,请坚持使用您的方法。此解决方案将要求您删除该行。

第二,方法是:

spyOn(component.dialog, 'open')

您正在为open引用的对象中的component.dialog实例方法安装 proxy 。在这种情况下,您先前注册的空对象。

尽管该对象没有这样的成员,但是jasmine会在其位置动态添加代理。这就是为什么您没有看到类似this.dialog.open is not a function的错误的原因。

最后,每次与代理交互时,代理都会记录有关这些交互的信息,并将呼叫重定向到原始open成员。由于没有a function with no return will be used in its place的原始实现,因此最终会触发accessing foo of undefined

TL; DR;

删除{ provide: MatDialog, useValue: {} }并使用以下命令模拟所需的MatDialogRef实例:

import { EMPTY} from 'rxjs';

it('openDialog() should open a dialog', () => {
    const openDialogSpy = spyOn(component.dialog, 'open')
        .and
        .returnValue({afterClosed: () => EMPTY});

    component.openDialog();

    expect(openDialogSpy).toHaveBeenCalled();
});

答案 1 :(得分:-2)

您可以尝试以下

     let dialogSpy: jasmine.Spy;
     let dialogRefSpyObj = jasmine.createSpyObj({ afterClosed : of({}), close: 
     null });
dialogRefSpyObj.componentInstance = { body: '' };

beforeEach(() => {
    dialogSpy = spyOn(TestBed.get(MatDialog), 'open').and.returnValue(dialogRefSpyObj);
});

OR

simplepluginclass.php
相关问题