从ngOnInit调用的Angular 2单元测试函数 [英] Angular 2 unit test function called from ngOnInit

查看:126
本文介绍了从ngOnInit调用的Angular 2单元测试函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试对组件内部的功能进行单元测试,此功能是根据初始条件从ngOnInit调用的:

I'm trying to unit test a function inside a component, this function is called from ngOnInit based on an inital condition:

ngOnInit() {
    if (this.list.length === 0) {
        return this.loadData();
    }

    return this.isLoading = false;
}

// I'm calling here because it could also be called from button on the UI
loadData() {
    this.apiService.apiGet().subscribe((response) => {
        // handle data
        return this.isLoading = false;
    }, (error) => {
        // handle error
        return this.isLoading = false;
    })
}

但是我无法测试它,除非我在测试中手动调用该函数.这是我的测试代码:

But I'm not able to test it unless I call the function manually on the tests. This is my test code:

// THIS CODE WORKS
it('should be false after calling loadData()', async(() => {
    component.loadData();
    fixture.detectChanges();

    fixture.whenStable().then(() => {
        expect(component.isLoading).toBeFalsy();
    });
}));

// THIS CODE DOESN'T work
it('should be false after calling loadData()', async(() => {
    spyOn(component,'loadData').and.returnValue({code:'success'});
    fixture.detectChanges();

    fixture.whenStable().then(() => {
        expect(component.isLoading).toBeFalsy();
    });
}));

这也是我用来模拟apiGet函数的一段代码:

Also this is the piece of code I'm using to mock the apiGet function:

apiGet() {
    return Observable.of({ data: 'success' });
}

但是我知道正在执行ngOnInit并且正在调用该函数,因为此测试通过:

However I know the ngOnInit is being executed and the function is being called because this test pass:

it('should be called if list array is empty', () => {
    spyOn(component,'loadData').and.returnValue({code:'success'});
    fixture.detectChanges();

    expect(component.loadData).toHaveBeenCalled();
});

我做错了什么?为什么测试失败并没有达到最终的承诺?

What am I doing wrong? Why the test failling doesn't get to the ending promise?

推荐答案

此模拟方法未设置isLoading,但它返回的值与此处无关:

This mocked method doesn't set isLoading, while it returns a value which is irrelevant here:

spyOn(component,'loadData').and.returnValue({code:'success'});

因此,它的行为明显不同于实际方法.如果这意味着使这个期望为假,那么就是这样:

So its behaviour clearly differs from the real method. If this means that this makes this expectation false, then that's it:

expect(component.isLoading).toBeFalsy();

测试此内容的正确方法是逐行在几个独立的规范中对此进行测试:

The proper way to test this is to test this in several isolated specs, line by line:

// ngOnInit test
spyOn(component, 'loadData');
this.list.length = 0;
fixture.detectChanges();
expect(component.loadData).toHaveBeenCalled();
expect(component.isLoading).toBe(true);

// ngOnInit test
spyOn(component, 'loadData');
this.list.length = 1;
fixture.detectChanges();
expect(component.loadData).not.toHaveBeenCalled();
expect(component.isLoading).toBe(false);

// loadData test
const apiServiceMock = {
  apiGet: jasmine.createSpy().and.returnValue(Observable.of(...))
};
this.apiService = apiServiceMock; // or mock via DI
spyOn(component, 'loadData').andCallThrough();
fixture.detectChanges();
// OR
// component.loadData()
expect(component.loadData).toHaveBeenCalled();
expect(apiServiceMock.apiGet).toHaveBeenCalled()
expect(component.isLoading).toBe(false);

// loadData test
const apiServiceMock = {
  apiGet: jasmine.createSpy().and.returnValue(Observable.throw(...))
};
// the rest is same

// loadData test
const apiServiceMock = {
  apiGet: jasmine.createSpy().and.returnValue(Observable.empty())
};
fixture.detectChanges();
expect(component.loadData).toHaveBeenCalled();
expect(apiServiceMock.apiGet).toHaveBeenCalled()
expect(component.isLoading).toBe(true);

这篇关于从ngOnInit调用的Angular 2单元测试函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆