Невозможно прочитать свойство afterClosed of undefined при модульном тестировании MatDialog в Jasmine - PullRequest
0 голосов
/ 19 февраля 2019

Я получаю следующую ошибку от Кармы Жасмин:
TypeError: Cannot read property 'afterClosed' of undefined

Я искал искренне, но не смог найти решение в переполнении стека или в других источниках.

ЭтоВот как я открываю MatDialog в моем компоненте:(Как задокументировано )

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 голосов
/ 19 февраля 2019

Давайте разберем вашу проблему шаг за шагом.

Сначала , зарегистрировав

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

Ваш испытательный стенд будет вводить объект без поведения (например,методы экземпляра / члены) всякий раз, когда необходимо разрешить MatDialog.

Это на самом деле не нужно, поскольку вы импортируете MatDialogModule в свой тестовый стенд, поэтому экземпляр MatDialog может быть решен без проблем. Но давайте придерживаться вашего подхода. Это решение потребует от вас удалить эту строку.

Секунда , выполнив:

spyOn(component.dialog, 'open')

youустанавливаем прокси для метода экземпляра open в объекте, на который ссылается component.dialog.В этом случае пустой объект, который вы зарегистрировали ранее.

Несмотря на то, что у объекта нет такого члена, Жасмин будет динамически добавлять прокси вместо него.Вот почему вы не видите ошибку, такую ​​как this.dialog.open is not a function.

И наконец , при каждом взаимодействии с прокси будет записываться информация об этих взаимодействиях и перенаправляться вызовы наоригинальный open член.Поскольку исходной реализации не было, вместо нее будет использоваться функция без возврата , которая, наконец, вызовет 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();
});
0 голосов
/ 19 февраля 2019

Вы можете попробовать ниже

{provide: MatDialog, useClass: MatDialogMock} // Add this in the providers array


export class MdDialogMock {
  // When the component calls this.dialog.open(...) we'll return an object
  // with an afterClosed method that allows to subscribe to the dialog result observable.
  open() {
    return {
      afterClosed: () => Observable.of({})
    };
  }
};

ИЛИ

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