I have a class that I need to test and it has two services that use two different EventEmitters (event import and @angular/core). The problem is that if I import one of these EventEmitters I can't import the other but with only one EventEmitter the test fails.
This is my component code
@Component({
selector: "app-mug",
templateUrl: "./mug.component.html",
styleUrls: ["./mug.component.scss"],
})
export class MugComponent implements OnInit
{
@Output() nav: EventEmitter<number> = new EventEmitter<number>();
public mug: Mug= new Mug();
constructor(
public constants: Constants,
public mugService: mugService,
public basicService: BasicService,
public toolsService: ToolsService,
private modalService: NgbModal,
)
ngOnInit() {
this.basicService.siteChange.subscribe((value) => {
this.mugService.filterC.id = value;
this.mugService.getRelatedMugs();
});
}
public openModal(contentType: string): void {
this.toolsService.eventEmitter.removeAllListeners();
this.toolsService.eventEmitter.addListener("close-modal", () =>
this.toolsService.eventEmitter.removeAllListeners()
);
this.toolsService.eventEmitter.addListener(
"contentEvent",
(content) => {
this.setContent(contentType, content);
}
);
const data = {
component: ModalSearchComponent,
input: inputList,
ModalTitle: "Mug finder",
};
const modalC = this.modalService.open(ModalContainerComponent, {
size: "lg",
backdrop: "static",
});
modalC.componentInstance.showComponent(data);
}
}
This is my Spec.ts code
import { EventEmitter } from "events";
//import { EventEmitter } from "@angular/core";
describe("MugComponent", () => {
let component;
const constants: Constants = new Constants();
let mugService = jasmine.createSpyObj("mugService", [
"filterC",
"getRelatedMugs",
]);
let modalService = jasmine.createSpyObj("modalService", ["open"]);
let basicService = jasmine.createSpyObj("basicService", [ "siteChange"]);
let toolsService = jasmine.createSpyObj("toolsService", ["toRoute"], {
eventEmitter: new EventEmitter(),
});
//It needs a different import of EventEmitter
//basicService.siteChange = new EventEmitter<number>(null);
beforeEach(() => {
component = new MugComponent(
constants,
mugService,
basicService,
toolsService,
modalService,
);
component.mug = new Mug();
});
it("should call getRelatedMugs", fakeAsync(() => {
component.ngOnInit();
tick();
expect(mugService.getRelatedMugs).toHaveBeenCalled();
}));
//this also fail with modalC.componentInstance
it("should call setContent openModal", fakeAsync(() => {
component.openModal();
tick();
expect(component.setContent).toHaveBeenCalled();
}));
});
These are the errors
HeadlessChrome 102.0.5005 (Windows 10.0.0) MugComponent Comprobamos ngOnInit FAILED
TypeError: Cannot read properties of undefined (reading 'subscribe')
HeadlessChrome 102.0.5005 (Windows 10.0.0) MugComponent Comprobando openModal FAILED
TypeError: Cannot read properties of undefined (reading 'componentInstance')
Thanks.
CodePudding user response:
The reading property subscribe
of undefined is because siteChange
is not mocked correctly.
When you do:
let basicService = jasmine.createSpyObj<BasicService>("basicService", [ "siteChange"]);
You are saying that siteChange
is a public method but in this case it is a property. Also, notice the <BasicService>
generic supplied, doing so well help you catch errors.
For a quick unblock, try this:
let basicService = { siteChange: of('1') };
For reading componentInstance
of undefined, make modal.open return what is required.
let modalService = jasmine.createSpyObj("modalService", ["open"]);
// Mock here or before the openModal is called
modalService.open.and.returnValue({
componenntInstance: {
showComponent: () => null,
}
});
....
component = new MugComponent(
constants,
mugService,
basicService,
toolsService,
modalService,
);
Edit
You need to mock the toolsService
differently, I am not sure if new EventEmitter()
has those methods that are being called.
Mock like this:
let toolsService = jasmine.createSpyObj("toolsService", ["toRoute"], {
eventEmitter: {
addListener: () => null,
removeAllListeners: () => null,
// keep adding all the rest you need
}
});
If you're new, I highly recommend for you to take your time and read this resource, it should help you a lot: https://testing-angular.com/.