When testing a component that dynamically opened a dialog using Angular Material (2), I was getting an error I didn’t immediately expect. The MdDialogModule was added to the imports, so my TestBed knew what was going on but my dynamically loaded Component caused problems.
Okay, researching the problem online gave me an issue on Github for the angular repository. It suggested the following in the beforeEach block:
[code language=“javascript“]
TestBed.overrideModule(BrowserDynamicTestingModule, {
set: {
entryComponents: [OfferFormDialogComponent],
},
});
[/code]
Sure, this solved the problem but it then causes an actual dialog to be opened during our tests. Well I really just want to test if the framework class gets called. I don’t want to test if the framework actually does what it promises.
It turns out, the solution is much cleaner, if you just mock instead of actually calling the MDDialog method.
So instead of
[code language=“javascript“]
spyOn(component.dialog, ‚open‘).and.callThrough();
[/code]
we do
[code language=“javascript“]
let mockDialogRef = new MdDialogRef(new OverlayRef(null,null,null,null),{});
mockDialogRef.componentInstance = new OfferFormDialogComponent(null, null);
spyOn(component.dialog, ‚open‘).and.returnValue(mockDialogRef);
[/code]
and later in the test spec
[code language=“javascript“]
it(’should open the dialog on clicking the button‘, fakeAsync(() => {
expect(component.dialog.open).toHaveBeenCalledTimes(0);
clickAddNewButton(component, fixture);
fixture.detectChanges();
tick();
expect(component.dialog.open).toHaveBeenCalled();
}));
[/code]
This way, a clean test of the component without too many dependency is possible. Yes, I am creating a new instance of my OfferFormDialogComponent, but since its constructor doesn’t do anything anyways, and its not active itself, it’s OK.
The whole test and class can be found on github/gist
Tests
Component