Unit testing angular 5 component with @ViewChild Unit testing angular 5 component with @ViewChild angular angular

Unit testing angular 5 component with @ViewChild


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();    });});


You can mock ChildComponent, so you can test ParentComponent in isolation and don't need to assign ChildComponent manually.

This is required if ParentComponent.childComponent is private and it is almost required if ChildComponent has many dependencies.

Your test file should look like this:

import { ComponentFixture, TestBed } from '@angular/core/testing';import { ChildComponent } from './child.component';import { ParentComponent } from './parent.component';@Component({  selector: 'child-component',  template: '',  providers: [{ provide: ChildComponent, useClass: ChildStubComponent }]})class ChildStubComponent {  childMethod = jasmine.createSpy('childMethod');}describe('ParentComponent', () => {S  let component: ParentComponent;  let fixture: ComponentFixture<ParentComponent>;  beforeEach(() => {    TestBed.configureTestingModule({      declarations: [ ParentComponent, ChildStubComponent ]    }).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();  });});

Credits:Idea from Angular inDepth.Based on @Anuradha Gunasekara's answer.