使用@ViewChild单元测试角度5组件

Jac*_*oni 7 unit-testing testbed viewchild angular

我正在使用角度5.2.0。我有一个子组件

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

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

    public childMethod() {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

和一个父组件,该组件通过 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

我要进行单元测试,以证明的调用parentMethod导致的调用childMethod。我有以下几点:

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

});
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用,我明白了Error: <spyOn> : could not find an object to spy upon for childMethod()

而且,这不是单元测试,因为我使用了真正的ChildComponent而不是模拟对象。我尝试创建一个MockChildComponent并将其添加到中declarationsexport但是得到了相同的结果。有什么帮助吗?

我知道也有类似的帖子,但是它们是针对不同版本的angular的,它们并没有帮助。

Anu*_*ara 15

你可以做这样的事情。

ChildComponent为此创建一个间谍对象。

const childComponent = jasmine.createSpyObj('ChildComponent', ['childMethod']);
Run Code Online (Sandbox Code Playgroud)

然后在测试中将组件的子组件属性设置为您创建的间谍。

  component.childComponent =  childComponent;
Run Code Online (Sandbox Code Playgroud)

您的测试文件应如下所示。

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

});
Run Code Online (Sandbox Code Playgroud)

  • 谢谢伙计,这很完美!我没有想到使用createSpyObj,这才是关键! (4认同)
  • 是的,记住单元测试是**测试单个单元**。所以你不必测试或声明真正的子组件。由于您没有测试模板,因此您可以为子组件创建一个间谍。 (2认同)