在 Jasmine 中对 MatDialog 进行单元测试时,无法读取未定义的属性“afterClosed" [英] Cannot read property 'afterClosed' of undefined when unit testing MatDialog in Jasmine

查看:17
本文介绍了在 Jasmine 中对 MatDialog 进行单元测试时,无法读取未定义的属性“afterClosed"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从 Karma Jasmine 收到以下错误:
TypeError: 无法读取未定义的属性afterClosed"

I get the following error from Karma Jasmine:
TypeError: Cannot read property 'afterClosed' of undefined

我真诚地搜索,但在 Stack Overflow 或其他来源中找不到解决方案.

I searched sincerely, but I could not find a solution in Stack Overflow or in other sources.

这是我在组件中打开 MatDialog 的方式:
(如已记录)

This is how I open the MatDialog in my component:
(Like documented)

constructor(public dialog: MatDialog) {}

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

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

这是我的单元测试配置:

This is my unit test config:

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?

Do I have to mock the MatDialog or the MatDialogReference?

推荐答案

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

Lets break your issue step by step.

首先,通过注册

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

每当需要解析 MatDialog 时,您的测试平台都会注入一个没有行为的对象(例如实例方法/成员).

Your test bed will inject a an object with no behavior (eg. instance methods/members) whenever MatDialog needs to be resolved.

这并不是真正必要的,因为您正在将 MatDialogModule 导入您的测试台,因此可以毫无问题地解决 MatDialog 的实例.但让我们坚持您的方法.此解决方案将要求您删除该行.

This isn't truly necessary, as you are importing the MatDialogModule into your test bed, so an instance of MatDialog can be resolved without issues. But lets stick to your approach. This solution will require you to remove that line.

第二,通过做:

spyOn(component.dialog, 'open')

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

you are installing a proxy for the open instance method in the object referenced by component.dialog. In this case, the empty object that you registered previously.

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

Despite the fact that the object does not have such a member, jasmine will dynamically add the proxy in its place. That is why you don´t see an error like this.dialog.open is not a function.

最后,每当与之交互时,代理将记录有关这些交互的信息并将调用重定向到原始open 成员.由于没有原始实现,一个没有返回的函数将使用,最终会触发访问未定义的foo.

Lastly, whenever interacted with, the proxy will record information about those interactions and redirect the calls to the original open member. Because there was no original implementation, a function with no return will be used in its place, which will finally trigger the accessing foo of undefined.

TL;DR;

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

Remove { provide: MatDialog, useValue: {} } and use the following in order to mock the required MatDialogRef instance:

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();
});

这篇关于在 Jasmine 中对 MatDialog 进行单元测试时,无法读取未定义的属性“afterClosed"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆