【问题标题】:Angular 2 unit test function called from ngOnInit从 ngOnInit 调用的 Angular 2 单元测试函数
【发布时间】:2017-11-20 21:22:54
【问题描述】:

我正在尝试对组件内的函数进行单元测试,该函数是根据初始条件从 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();
});

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

【问题讨论】:

    标签: javascript angular unit-testing


    【解决方案1】:

    这个模拟的方法没有设置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);
    

    【讨论】:

    • 我的问题是我用()调用了spy方法。谢谢你:)
    猜你喜欢
    • 2020-08-08
    • 1970-01-01
    • 2016-05-25
    • 2016-06-26
    • 2018-09-14
    • 2017-04-04
    • 2016-12-29
    • 1970-01-01
    相关资源
    最近更新 更多