web-dev-qa-db-fra.com

Test unitaire angular 5 avec @ViewChild

J'utilise angular 5.2.0. J'ai un composant enfant

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

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

    public childMethod() {
        ...
    }
}

et un composant parent qui accède à l'enfant via ViewChild

import { Component, ViewChild } from '@angular/core';
import { ChildComponent } from 'child.component';

@Component({
    template: `<child-component #child><\child-component>`
})
export class ParentComponent {

    @ViewChild('child')
    public child: ChildComponent;

    public parentMethod() {
        this.child.childMethod();
    }
}

Je veux un test unitaire prouvant qu'une invocation de parentMethod provoque une invocation de childMethod. J'ai ce qui suit:

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

});

Pourtant, cela ne fonctionne pas et j'obtiens Error: <spyOn> : could not find an object to spy upon for childMethod().

De plus, ce n'est pas un test unitaire, car j'utilise le vrai ChildComponent au lieu d'une maquette. J'ai essayé de créer un MockChildComponent et de l'ajouter à declarations et export mais j'ai obtenu le même résultat. De l'aide?

Je sais qu'il existe des articles similaires, mais ils concernent différentes versions d'angular et ils n'ont pas aidé.

11
Jacopo Lanzoni

Vous pouvez faire quelque chose comme ça.

Créez un objet espion pour le ChildComponent comme ceci.

const childComponent = jasmine.createSpyObj('ChildComponent', ['childMethod']);

Ensuite, dans le test, définissez la propriété du composant enfant du composant sur l'espion que vous avez créé.

  component.childComponent =  childComponent;

Votre fichier de test devrait ressembler à ceci.

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(TaskListPaginatorComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
});

    it('should invoke childMethod when parentMethod is invoked', () => {
        component.childComponent =  childComponent;
        component.parentMethod();
        expect(childComponent.childMethod).toHaveBeenCalled();
    });

});
4
Anuradha Gunasekara