2017-08-02 92 views
2

我目前正在嘗試調用一個函數,它調用一個http請求服務,然後在訂閱部分(調用一個函數並設置一個變量)做一些事情。到目前爲止,我的方法只是調用函數,我認爲請求服務將被自動調用,所以訂閱部分將被執行。但是,我覺得這不是它做的方式,因爲它不工作。Angular2 - 測試一個函數,調用一個http服務

我要測試的功能:

public trainBot() { 
    this.isTraining = true; 
    this.requestsService.trainModel(this.botId, false) 
     .subscribe(response => { 
     this.trainingStatus = this.trainingStatusMapping[response['status']]; 
     this.pollTrainingStatus(); 
     }); 
    } 

我的測試,到目前爲止(不工作)。

it('should poll the training status',() => { 
    spyOn(component, 'pollTrainingStatus').and.callThrough(); 
    component.trainBot(); 
    fixture.detectChanges(); 
    expect(component.pollTrainingStatus).toHaveBeenCalled(); 
    }); 

那麼,誰能告訴我如何測試.subscribe內部的部分(...部分

更新:

有人建議我加入的returnValue和異步我。測試他們仍然沒有工作,但現在看起來就像是:

it('should poll the training status', fakeAsync(() => { 
    component.trainBot(); 
    spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'})); 
    spyOn(component, 'pollTrainingStatus').and.callThrough(); 
    fixture.detectChanges(); 
    tick(1); 
    expect(service.trainModel).toHaveBeenCalled(); 
    expect(component.pollTrainingStatus).toHaveBeenCalled(); 
    })); 

的錯誤是一樣的

+0

您能分享您收到的錯誤或失敗測試的輸出結果嗎? – Kevin

+0

@Kevin「期待間諜pollTrainingStatus被調用。」這意味着pollTrainingStatus()不叫 – threxx

+0

看看這個問題:[angular2測試使用jasmine的訂閱方法](https://stackoverflow.com/questions/40080912/angular2-testing-using-jasmine-for-subscribe-method) 。讓我知道如果答案在那裏適合你。 – Kevin

回答

4

首先,你需要在你運行的方法trainBot創建您的間諜()。這應該修復你的測試。

it('should poll the training status',() => { 
    spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'})); 
    spyOn(component, 'pollTrainingStatus'); 

    component.trainBot(); 

    expect(service.trainModel).toHaveBeenCalled(); 
    expect(component.pollTrainingStatus).toHaveBeenCalled(); 
})); 

但是,讓我們來談談您的測試策略。

說實話,你測試的是一個組件,而不是服務,所以你不應該讓服務方法調用。

spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'})); 

此外,單元測試應測試可能的最小的事情。您實際上正在測試回調,回調可能應該是一個命名方法,而不是匿名箭頭函數。然後您可以在其他測試中測試並驗證回調的功能。

public trainBot() { 
    this.isTraining = true; 
    this.requestsService.trainModel(this.botId, false) 
     .subscribe(response => this.onTrainbotSuccess(response)); 
} 

public onTrainbotSuccess(response) { 
    this.trainingStatus = this.trainingStatusMapping[response['status']]; 
    this.pollTrainingStatus(); 
} 

這個測試,可以測試該反應的方法獲取調用

it('should call service.trainModel',() => { 
    spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'})); 

    component.trainBot(); 

    expect(service.trainModel).toHaveBeenCalled(); 
}); 

it('should send success responses to onTrainbotSuccess()',() => { 
    spyOn(component, 'onTrainbotSuccess'); 
    spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'})); 

    component.trainBot(); 

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

現在我們可以寫具體的成功回調做什麼測試。

it('should poll the training status',() => { 
    spyOn(component, 'pollTrainingStatus'); 

    component.onTrainbotSuccess({'status': 'training'}); 

    expect(component.pollTrainingStatus).toHaveBeenCalled(); 
}); 
+0

哦,我明白了!這更有意義!謝謝! – threxx

0

傳遞給subscribe()的函數被異步調用。這意味着您的斷言在調用this.pollTrainingStatus()之前運行。您需要使用async() or fakeAsync() utility function

在代碼可以是這樣的(如果使用fakeAsync()):

import { fakeAsync } from '@angular/core/testing'; 

it('should poll the training status', fakeAsync(() => { 
    ... 
    expect(component.pollTrainingStatus).toHaveBeenCalled(); 
})); 
+0

我補充說,仍然沒有工作,測試結果相同 – threxx

+0

您是否在[docs](https://angular.io/guide/testing#the-fakeasync-function)中添加了'tick()'? – buoto

+0

是的,我用tick()和tick(1) – threxx

相關問題