简体   繁体   中英

Unit testing angular 5 component with @ViewChild

I am using angular 5.2.0. I have a child component

import { Component } from '@angular/core';

@Component({
    template: `<div><\div>`
})
export class ChildComponent {

    public childMethod() {
        ...
    }
}

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.

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

Alternatively, quick and easy way of covering such code....

component.myDatePicker = { toggleCalender: () => Promise.resolve()} as unknown as AngularMyDatePickerDirective;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM