Angular: How to Mock Matdialogref While Testing

I have a DialogComponent that has the following constructor where Dialog is a custom object:

constructor(
    public dialogRef: MatDialogRef<CustomDialogComponent>,
    @Inject(MAT_DIALOG_DATA) public data: Dialog
)

I created the following TestBed in Angular4:

data = new Dialog()
data.message = 'Dialog Message'

TestBed.configureTestingModule({
    imports: [MaterialModules],
    declarations: [CustomDialogComponent],
    providers: [MatDialogRef, { provide: Dialog, useValue: data }]
})

TestBed.overrideModule(BrowserDynamicTestingModule, {
    set: {
        entryComponents: [CustomDialogComponent]
    }
})
await TestBed.compileComponents()

But I get the following error:

Failed: Can't resolve all parameters for MatDialogRef: (?, ?, ?).
Error: Can't resolve all parameters for MatDialogRef: (?, ?, ?).

changing providers to:

providers: [
    { provide: MatDialogRef, useValue: {} },
    { provide: MAT_DIALOG_DATA,  useValue: data }
]

results in the following error:

Error: No provider for Dialog!

How do I resolve this?

2

5 Answers

I solved it by changing the component constructor to:

constructor(
  public dialogRef: MatDialogRef<CustomDialogComponent>,
  @Inject(MAT_DIALOG_DATA) public data: Dialog | any
)

The providers in the TestBed were:

providers: [{ provide: MatDialogRef, useValue: {} }, { provide: MAT_DIALOG_DATA, useValue: data }]
4

If you use at least one MatDialogRef method, you should create a mock. For example I use the close() method. Without it errors would be generated so I made the below class with an empty method.

export class MatDialogRefMock {
    close(value = '') {

    }
}

and use that instead of an empty value, with useClass

{ provide: MatDialogRef, useClass: MatDialogRefMock },
2

Import MatDialogModule and MatDialogRef from angular/material/dialog instead of angular/material. Import the ModalDialogModule and provide providers for MatDialogRef in your TestBed.

Import {MatdialogModule,MatDialogRef} from '@angular/material/dialog';

TestBed.configureTestingModule({
declarations: [componentName],
imports: [MatdialogModule],
providers: [{provide : MatDialogRef, useValue : {}}]
});
2

To solve this problem, you can do the following steps:

1- You used the data as input to the dialog and used it in the constructor to set the variables. (in .ts)

  constructor(public dialogRef: MatDialogRef<any>,
          @Inject(MAT_DIALOG_DATA) public data: any) {
     this.ip= data.ip;
     this.name= data.name;
  }

2- We should create fake data, (in .spec.ts)

const data = {
    ip: '1.1.1.1',
    name: 'test'
 }

3- We define provider as follows And we introduce data, (in .spec.ts)

 providers: [
   {provide: MatDialogRef, useValue: {}},
   {provide: MAT_DIALOG_DATA, useValue: data},
  ]

4- full code in .spec.ts

import {async, ComponentFixture, TestBed} from '@angular/core/testing';

import {CustomDialogComponent} from './backup-list.component';
import {TranslateModule} from '@ngx-translate/core';
import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from '@angular/material';
import {BrowserDynamicTestingModule} from '@angular/platform-browser-dynamic/testing';
import {NO_ERRORS_SCHEMA} from '@angular/core';

const data = {
    ip: '1.1.1.1',
    name: 'test'
 };

describe('BackupListComponent', () => {
   let component: BackupListComponent;
   let fixture: ComponentFixture<BackupListComponent>;

    beforeEach(async(() => {
    TestBed.configureTestingModule({
        declarations: [CustomDialogComponent],
        imports: [
            TranslateModule.forRoot(),
            MatDialogModule,
            BrowserDynamicTestingModule
        ],
        providers: [
            {provide: MatDialogRef, useValue: {}},
            {provide: MAT_DIALOG_DATA, useValue: data},
        ],
        schemas: [NO_ERRORS_SCHEMA]
    })
        .compileComponents();
  }));
 });

You can do this by the help of jasmine spy, as follow:

Step 1: Define the mock data

  const data = {
    title: 'title',
    message: 'message',
    summary: 'my summary'
  };

Step 2: Create jasmine spy for MatDialogRef (Write this inside beforeEach block)

const matDialogSpy = jasmine.createSpyObj('MatDialogRef', ['onNoClick', 'closeDialog']);

onNoClick and closeDialog are methods inside MessagePopupComponnet

Step 3: Configure the TestBed as follow:

  providers: [
    {
      provide: MatDialogRef,
      useValue: matDialogSpy
    },
    {
      provide: MAT_DIALOG_DATA,
      useValue: data
    }
  ]

For the ref, I've provided the full code below:

import { DebugElement } from "@angular/core";
import { async, ComponentFixture, TestBed } from "@angular/core/testing";
import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material";

import { MessagePopupComponent } from "./message-popup.component";


describe('MessagePopup', () => {
  let fixture: ComponentFixture<MessagePopupComponent>;
  let component: MessagePopupComponent;
  let el: DebugElement;
  let matDialogRef;

  const data = {
    title: 'title',
    message: 'message',
    summary: 'my summary'
  };

  beforeEach(async(() => {

    const matDialogSpy = jasmine.createSpyObj('MatDialogRef', ['onNoClick', 'closeDialog']);

    TestBed.configureTestingModule({
      declarations: [MessagePopupComponent],
      providers: [
        {
          provide: MatDialogRef,
          useValue: matDialogSpy
        },
        {
          provide: MAT_DIALOG_DATA,
          useValue: data
        }
      ]
    }).compileComponents()
    .then(() => {
      fixture = TestBed.createComponent(MessagePopupComponent);
      component = fixture.componentInstance;
      el = fixture.debugElement;
      matDialogRef = TestBed.get(MatDialogRef);
    });

  }));

  fit('should create Message Popup component', () => {
    expect(component).toBeTruthy('Message popup not created')
  });

});
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Alexander Ross

Alexander Ross

Gaming, Esports & Interactive Media Writer

Alexander Ross has covered the video game industry for a decade, writing deep dives on game design, esports tournaments, VR developments, and gaming culture.

Share this article
Twitter Facebook Pinterest