MatDialog Service Unit Test Angular 6 Error MatDialog Service Unit Test Angular 6 Error angular angular

MatDialog Service Unit Test Angular 6 Error


Testing mat-dialogs can be tricky. I tend to use a spy object for the return from a dialog open (dialogRefSpyObj below) so I can more easily track and control tests. In your case it might look something like the following:

describe('ModalService', () => {    let modalService: ModalService;    let dialogSpy: jasmine.Spy;    let dialogRefSpyObj = jasmine.createSpyObj({ afterClosed : of({}), close: null });    dialogRefSpyObj.componentInstance = { body: '' }; // attach componentInstance to the spy object...    beforeEach(() => {        TestBed.configureTestingModule({            imports: [MatDialogModule],            providers: [ModalService]        });        modalService = TestBed.get(ModalService);    });    beforeEach(() => {        dialogSpy = spyOn(TestBed.get(MatDialog), 'open').and.returnValue(dialogRefSpyObj);    });    it('open modal ', () => {        modalService.open(TestComponent, '300px');        expect(dialogSpy).toHaveBeenCalled();        // You can also do things with this like:        expect(dialogSpy).toHaveBeenCalledWith(TestComponent, { maxWidth: '100vw' });        // and ...        expect(dialogRefSpyObj.afterClosed).toHaveBeenCalled();    });});


I have a better solution that still works on 2019

header.component.ts

import { BeforeLogOutComponent } from '@app-global/components/before-log-out/before-log-out.component';  /**   * The method triggers before the logout.   * Opens the dialog and warns the user before log Out.   */  public beforeLogOut(): void {    this._dialog.open(BeforeLogOutComponent, { width: '400px', disableClose: false, panelClass: 'dialog_before_log_out' })    .afterClosed()    .subscribe((res) => {      if (res && res.action === true) { this.loggedOut(); }    }, err => {      console.error(err);    });  }

header.component.spec.ts

import { async, ComponentFixture, TestBed } from '@angular/core/testing';import { MatDialog } from '@angular/material';import { Observable, of } from 'rxjs';<<-- Create a MatDialog mock class -->>export class MatDialogMock {  // 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: () => of({action: true})    };  }}describe('HeaderComponent', () => {  let component: HeaderComponent;  let fixture: ComponentFixture<HeaderComponent>;  beforeEach(async(() => {    TestBed.configureTestingModule({      imports: [        MaterialModule, RouterTestingModule, HttpModule, BrowserAnimationsModule,        HttpClientModule, FlexLayoutModule,      ],      declarations: [        HeaderComponent,      ],      providers: [        { provide: MatDialog, useClass: MatDialogMock } <<-- look this      ]    })    .compileComponents();  }));  beforeEach(async() => {    fixture = TestBed.createComponent(HeaderComponent);    component = fixture.componentInstance;    component.ngOnInit();    component.ngAfterViewInit();    await fixture.whenStable();    fixture.detectChanges();  });  fit('should create', () => {    expect(component).toBeTruthy();  });  // I test the dialog here.  fit('should open the dialog', () => {    component.beforeLogOut();  });}


I do not have the exact answer for your case but I also did some tests on MatDialog. I can show you what I did. Maybe look at the inject() part:

(I deleted some things for clarity and confidentiality)

describe('MyDialogComponent', () => {  let dialog: MatDialog;  let overlayContainer: OverlayContainer;  let component: MyDialogComponent;  let fixture: ComponentFixture<MyDialogComponent>;  const mockDialogRef = {    close: jasmine.createSpy('close')  };  beforeEach(async(() => {    TestBed.configureTestingModule({      imports: [        BrowserAnimationsModule,        ReactiveFormsModule,        AngularMaterialModule,      ],      providers: [        { provide: MatDialogRef, useValue: mockDialogRef },        {          provide: MAT_DIALOG_DATA,          useValue: {            title: 'myTitle',          }        }      ],      declarations: [MyDialogComponent],    });    TestBed.overrideModule(BrowserDynamicTestingModule, {      set: {        entryComponents: [MyDialogComponent]      }    });    TestBed.compileComponents();  }));  beforeEach(inject([MatDialog, OverlayContainer],    (d: MatDialog, oc: OverlayContainer) => {      dialog = d;      overlayContainer = oc;    })  );  afterEach(() => {    overlayContainer.ngOnDestroy();  });  beforeEach(() => {    fixture = TestBed.createComponent(MyDialogComponent);    component = fixture.componentInstance;    fixture.detectChanges();  });  it('should create', () => {    expect(component).toBeTruthy();  });  it('onCancel should close the dialog', () => {    component.onCancel();    expect(mockDialogRef.close).toHaveBeenCalled();  });});