繁体   English   中英

Angular 2单元测试函数从ngOnInit调用

[英]Angular 2 unit test function called from ngOnInit

我正在尝试对组件内的一个函数进行单元测试,这个函数是根据一个初始条件从ngOnInit调用的:

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

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

// 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函数的一段代码:

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

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

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

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

我究竟做错了什么? 为什么测试费用没有达到最终的承诺?

这个isLoading方法没有设置isLoading ,而它返回一个与此无关的值:

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

所以它的行为明显不同于真正的方法。 如果这意味着这使得这个期望是错误的,那就是它:

expect(component.isLoading).toBeFalsy();

测试这个的正确方法是逐行测试几个隔离的规范:

// 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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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