Reputation: 1115
I'm trying to teach myself how to code with Angular and I have a problem. I am creating a app for myself and I have just implemented the Angular Material Dialog. I put this in a wrapper service and all seems well. So in a component I call the Wrapper Service to raise a modal like so...
public assignInstrument(instrument: any): void {
this.modalDialogWrapperService.openAssignmentWindow({
product: 'instrument',
type: instrument.type,
serial: instrument.serial,
id: instrument.id
});
}
the service method looks like so, notice I pass the name of a component I wish to raise in the modal window
openAssignmentWindow(instrument) {
const dialogRef = this.dialog.open(ChangeAssignmentComponent, {
data: instrument,
width: '693px',
height: '498px'
});
dialogRef.afterClosed().subscribe(() => {});
});
}
Everything works great! But as a good developer I should write unit tests... so to test my component I have the following test (I have included how I mock the Service and some other code to give an impression of the test file)
let modalDialogWrapperServiceSpy: jasmine.SpyObj<ModalDialogWrapperService>;
const mockModalDialogWrapperService = jasmine.createSpyObj('ModalDialogWrapperService', ['openAssignmentWindow']);
mockModalDialogWrapperService.openAssignmentWindow.and.returnValue({});
TestBed.configureTestingModule({
imports: [...],
declarations: [...],
providers: [{
provide: ModalDialogWrapperService,
useValue: mockModalDialogWrapperService
}]
}).compileComponents();
beforeEach(() => {
fixture = TestBed.createComponent(InstrumentsPageComponent);
modalDialogWrapperServiceSpy = TestBed.get(ModalDialogWrapperService);
component = fixture.componentInstance;
fixture.detectChanges();
})
describe('assignInstrument', () => {
it('should call the Modal Dialog Service', () => {
component.assignInstrument({});
expect(modalDialogWrapperServiceSpy.openAssignmentWindow).toHaveBeenCalledTimes(1);
});
});
This one test fails! With the error "Error: No component factory found for ChangeAssignmentComponent. Did you add it to @NgModule.entryComponents" - this seems odd as in my app.module file I declare "ChangeAssignmentComponent" in entryComponents and declarations arrays? I am confused - does anyone know what I could be doing wrong?
Upvotes: 30
Views: 19467
Reputation:
Testing is doubting.
More seriously, let me answer you.
In Angular, your components are handled by a module. When you use Material dialogs and snackers, you actually use a feature of the CDK, which is called Portal
. This allow you to create your components dynamically.
But when you do so, you have to add them to the entryComponents
of your module. You did it in your module, so you should also do it in your tests.
The syntax is
TestBed
.configureTestingModule(...)
.overrideModule(BrowserDynamicTestingModule, { set: { entryComponents: [YourComponent] } });
Upvotes: 53
Reputation: 51
If someone struggling to find BrowserDynamicTestingModule
just use BrowserModule
instead.
TestBed
.configureTestingModule(...)
.overrideModule(BrowserModule, { set: { entryComponents: [YourComponent] } });
Upvotes: 5
Reputation: 1493
there are two places at which this is supposed to be done....entry components and also at declarations(while configuring your testing module)....
TestBed
.configureTestingModule({
declarations: [YourComponent],
})
.overrideModule(BrowserDynamicTestingModule, { set: { entryComponents: [YourComponent] } });
Upvotes: 20