首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Angular 2中测试ngOnChanges生命周期挂钩

在Angular 2中测试ngOnChanges生命周期挂钩
EN

Stack Overflow用户
提问于 2016-05-24 16:58:32
回答 3查看 31.5K关注 0票数 37

给定以下代码,我尝试测试Angular2的ngOnChanges生命周期钩子:

代码语言:javascript
复制
import {
    it,
    inject,
    fdescribe,
    beforeEachProviders,
} from '@angular/core/testing';

import {TestComponentBuilder} from '@angular/compiler/testing';

import {Component, OnChanges, Input} from '@angular/core';

@Component({
    selector: 'test',
    template: `<p>{{value}}</p>`,
})
export class TestComponent implements OnChanges {
    @Input() value: string;

    ngOnChanges(changes: {}): any {
        // should be called
    }
}

fdescribe('TestComponent', () => {
    let tcb: TestComponentBuilder;

    beforeEachProviders(() => [
        TestComponentBuilder,
        TestComponent,
    ]);

    beforeEach(inject([TestComponentBuilder], _tcb => {
        tcb = _tcb;
    }));

    it('should call ngOnChanges', done => {
        tcb.createAsync(TestComponent).then(fixture => {
            let testComponent: TestComponent = fixture.componentInstance;

            spyOn(testComponent, 'ngOnChanges').and.callThrough();

            testComponent.value = 'Test';
            fixture.detectChanges();

            expect(testComponent.ngOnChanges).toHaveBeenCalled();
            done();
        }).catch(e => done.fail(e));
    });
});

不幸的是,测试失败了,出现消息Expected spy ngOnChanges to have been called.我知道在这个例子中我只能检查HTML元素的内容,但是我有一些代码需要在ngOnChanes生命周期钩子中测试,所以这对我来说不是一个解决方案。我也不想在测试中直接调用testComponent.ngOnChanges({someMockData});

如何从测试中设置TestComponent.value,以便调用ngOnChanges

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-10-29 16:50:44

我想我来派对有点晚了,不过这对将来的一些人可能会有用。

自从angular的RC5发布以来,测试有了一些变化。然而,这里的主要问题是,当以编程方式设置输入时,不会调用ngOnChangesSee this for more info。基本上,当输入通过仅供查看的传递时,OnChanges挂钩被触发为

这个问题的解决方案是让主机组件成为测试组件的父组件,并通过主机组件的模板传递输入。

以下是完整的工作代码:

代码语言:javascript
复制
import {Component, OnChanges, Input, ViewChild} from '@angular/core';
import { TestBed }      from '@angular/core/testing';

@Component({
    selector: 'test',
    template: `<p>{{value}}</p>`,
})
export class TestComponent implements OnChanges {
    @Input() value: string;

    ngOnChanges(changes: {}): any {
        // should be called
    }
}
/* In the host component's template we will pass the inputs to the actual
 * component to test, that is TestComponent in this case
 */
@Component({
    selector : `test-host-component`,
    template :
    `<div><test [value]="valueFromHost"></test></div>`
})
export class TestHostComponent {
    @ViewChild(TestComponent) /* using viewChild we get access to the TestComponent which is a child of TestHostComponent */
    public testComponent: any;
    public valueFromHost: string; /* this is the variable which is passed as input to the TestComponent */
}

describe('TestComponent', () => {

    beforeEach(() => {
        TestBed.configureTestingModule({declarations: [TestComponent,TestHostComponent]}); /* We declare both the components as part of the testing module */
    });

    it('should call ngOnChanges', ()=> {
        const fixture = TestBed.createComponent(TestHostComponent);
        const hostComponent = fixture.componentInstance;
        hostComponent.valueFromHost = 'Test';
        const component = hostComponent.testComponent;
        spyOn(component, 'ngOnChanges').and.callThrough();
        fixture.detectChanges();
        expect(component.ngOnChanges).toHaveBeenCalled();
    })


});
票数 68
EN

Stack Overflow用户

发布于 2017-02-22 21:18:28

您还可以选择手动调用ngOnChanges钩子,并将所需的更改对象传递到那里。但这并不设置组件属性,只调用更改逻辑。

代码语言:javascript
复制
const previousValue = moment('2016-03-01T01:00:00Z');
const currentValue = moment('2016-02-28T01:00:00Z');

const changesObj: SimpleChanges = {
  prop1: new SimpleChange(previousValue, currentValue),
};

component.ngOnChanges(changesObj);

请注意,这种方法可以很好地测试ngOnChanges内部的逻辑,但它不会测试@Input装饰器是否设置正确。

票数 27
EN

Stack Overflow用户

发布于 2017-08-21 19:55:46

在Angular 4中,要在测试时手动触发ngOnChanges(),您必须手动进行调用(如上所述),只需要匹配new call signature of SimpleChange()

代码语言:javascript
复制
let prev_value = 'old';
let new_value = 'new';
let is_first_change: boolean = false;

component.ngOnChanges({
  prop1: new SimpleChange(prev_value, new_value, is_first_change),
});
票数 24
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37408801

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档