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?
25 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 }] 4If 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 }, 2Import 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 : {}}] }); 2To 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