I am using angular 5.2.0. I have a child component
import { Component } from '@angular/core';
@Component({
template: `<div><div></div></div>`,
})
export class ChildComponent {
public childMethod() {
...
}
}
and a parent component which accesses the child via ViewChild
import { Component, ViewChild } from "@angular/core";
import { ChildComponent } from "child.component";
@Component({
template: `
<child-component #child>
<child-component></child-component>
</child-component>
`,
})
export class ParentComponent {
@ViewChild("child") child: ChildComponent;
public parentMethod() {
this.child.childMethod();
}
}
I want a unit test proving that an invocation of parentMethod
causes an invocation of childMethod
. I have the following:
import { NO_ERRORS_SCHEMA } from "@angular/core";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { ChildComponent } from "./child.component";
import { ParentComponent } from "./parent.component";
describe("ParentComponent", () => {
let component: Parentcomponent;
let fixture: ComponentFixture<Parentcomponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ParentComponent, ChildComponent],
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(TaskListPaginatorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it("should invoke childMethod when parentMethod is invoked", () => {
const childMethodSpy: jasmine.Spy = spyOn(component.child, "childMethod");
component.parentMethod();
expect(childMethodSpy).toHaveBeenCalled();
});
});
Yet, this does not work, and I get Error: <spyOn> : could not find an object to spy upon for childMethod()
.
Moreover, this is not a unit test, because I use the real ChildComponent instead of a mock. I tried creating a MockChildComponent and adding it to declarations
and export
but I got the same result. Any help?
I know there are similar post, but they are for different versions of angular, and they did not help.
You can do something like this.
Create a spy object for the ChildComponent
like this.
const childComponent = jasmine.createSpyObj('ChildComponent', ['childMethod']);
Then in the test, set the component's childComponent property to the spy that you have created.
component.childComponent = childComponent;
Your test file should look like this.
import { NO_ERRORS_SCHEMA } from "@angular/core";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { ChildComponent } from "./child.component";
import { ParentComponent } from "./parent.component";
describe("ParentComponent", () => {
let component: ParentComponent;
let fixture: ComponentFixture<ParentComponent>;
const childComponent = jasmine.createSpyObj("ChildComponent", [
"childMethod",
]);
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ParentComponent, ChildComponent],
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ParentComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it("should invoke childMethod when parentMethod is invoked", () => {
component.childComponent = childComponent;
component.parentMethod();
expect(childComponent.childMethod).toHaveBeenCalled();
});
});