2017-04-07 12 views
1

私はジャスミンでAngularJSのデータポーリングをテストする方法は?

コントローラロジックは、この

$onInit() { 
    this.requestRootLocations(); 
    this.startDataPolling(); 
} 

private startDataPolling() { 

    this.stop = this.$interval(() => 
    this.requestRootLocations() 
    , this.DATA_POLLING_INTERVAL); 
} 

private requestRootLocations() { 
     this.locationsService.requestRootElements().then(function (locationItem) { 
     ... 

     this.entityList = (locationItem["locations"] instanceof Array) ? locationItem["locations"] : []; 
     }.bind(this), function() { 
     console.log("Error on loading locations data."); 
     }); 
    } 

アップデートのように見える私のコントローラのテストデータのポーリングに悩みを持っている:サービスで httpリクエスト:

public requestRootElements() { 
     return this.$http.get(this.API + "locations").then((response) => response.data); 
    } 

これは正常に動作します期待通り。

テストケースはこの

it("should call http request on intervals", function() { 

    ctrl.$onInit(); 
    $httpBackend.whenGET(api + "locations").respond(200, locationData); 

    // advance in time by 1 seconds 
    $interval.flush(1000); 

    $httpBackend.expectGET(api + "locations"); 
    // after 1 seconds locations should be called once 
    $httpBackend.flush(); 

    expect(ctrl.counts.length).toBe(4); 
    expect(ctrl.entities.length).toBe(6); 

    $interval.flush(dataPollingInterval); 
    $httpBackend.expectGET(api + "locations"); //does not work, why? 
    $httpBackend.flush(); 

    // after the second call the data should be the same in this case 
    expect(ctrl.counts.length).toBe(4); 
    expect(ctrl.entities.length).toBe(6); 
}); 

のように見えますが、2番目expectGETにエラー

Error: Unsatisfied requests: GET /apiv1/locations

+0

これらの$ httpリクエストはどこにありますか?切り詰められたコードスニペットを投稿することは役に立ちません。これがコントローラで発生した場合は、完全に投稿してください。これがサービスで発生した場合は、コントローラとサービスの両方を送信してください。 – estus

+0

ありがとう、私は質問を更新しました – Juri

+0

まだなぜそれが失敗するか分からない。 DATA_POLLING_INTERVALが1000であることは明らかではありません。実際の問題は、複数のユニットが1つの統合テストに混在し、それほど効果的ではないということです。あまりにも多くの可動部品を導入し、同時に孤立してテストすることができなかったものはテストしません。答えを見てください。 – estus

答えて

0

は、ここでの問題は、ユニットが分離されていないということです。これはユニットテストではなく、統合テスト(コントローラ+サービス+ $インターバル)です。テストが赤色になると、どのユニットが故障したかは分かりません。

これをユニットテストするための適切な戦略は、テストされたユニット(コントローラ)以外のすべてを模擬することです。 $intervalもオプションで嘲笑することができます。実際にどのように動作するかテストする必要はありません。これは既にAngularによってテストされています。

constructor(...) { 
    ... 
    // bind callback method 
    this.dataPollingHandler = this.dataPollingHandler.bind(this); 
} 

$onInit() { 
    this.requestRootLocations(); 
    this.stop = this.$interval(this.dataPollingHandler, this.DATA_POLLING_INTERVAL); 
} 

private dataPollingHandler() { 
    this.requestRootLocations() 
} 

そしてそれは

spyOn(ctrl, 'requestRootLocations'); 

// unbind callback method 
ctrl.dataPollingHandler.call(null); 

expect(ctrl.requestRootLocations).toHaveBeenCalled(); 

... 

var intervalPromise = $q.resolve(); 
var intervalMock = jasmine.createSpy().and.returnValue(intervalPromise); 
var ctrl = $controller(..., { $interval: intervalMock }); 

ctrl.$onInit(); 
expect(ctrl.stop).toBe(intervalPromise); 
expect($intervalStub).toHaveBeenCalledWith(ctrl.dataPollingHandler, 1000); 

... 

var locationsServiceMock = { 
    requestRootLocations: jasmine.createSpy().and.returnValue($q.resolve(locationData)); 
} 

var ctrl = $controller(..., { locationsService: locationsServiceMock }); 
// now ctrl.requestRootLocations can be tested 
... 

ように試験することができるスイートユニットと統合テストの両方を有することがOKであるが、適切なコントローラおよびサービスユニットのテストが存在する場合、統合テストは、冗長になります。

+0

あなたはまったく正しいです。しかし、これは私が望む答えではありません。それは統合テストであり、何時間も経たないうちに試してみます。 $ httpBackend.expectGET(api + "locations"); $ interval.flush(1000); $ httpBackend.flush(); expect(ctrl.isEditing).toBe(false); //最初に呼び出した後に1つの要求を呼び出す必要があります $ httpBackend.expectGET(api + "locations"); $ interval.flush(dataPollingInterval); $ httpBackend.flush(); – Juri

+0

あなたのためにうれしいです、バックエンドの後に間隔をフラッシュすることは意味をなさないでしょう。しかし、それは言ったように、それはそのような$間隔をテストする意味がありません。これは既にAngularでテストされており、期待どおりに動作することを確認できます。この種の統合テストは、単体テストを置き換えることができず、カバレッジに役立たないため、通常は記述しないでください。 – estus

+0

これが役立つことを願っています。質問者が「テスト方法」への回答を得ようとしているのか、それともバグの修正を求めるのかは必ずしも明確ではありません。 – estus

関連する問題