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.
The @ViewChild decorator allows us to inject into a component class references to elements used inside its template, that's what we should use it for. Using @ViewChild we can easily inject components, directives or plain DOM elements.
find('ChildComponent'); const child1 = element.at(0); const child2 = element.at(1); expect(element. length). toBe(2); expect(child1.name()). toBe('ChildComponent'); expect(child1.
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();   }); });   
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With