2016-09-01 48 views
0

爲什麼在測試用例中要執行$scope.$apply()才能完成異步處理。

說,我有一個服務

angular.service("a",function($q){ 
    return { 
     getValue: function(){ 
      return $q.resolve(someObj) 
     } 
    } 
}) 

而且在我的測試

it("test this",function(done){ 
    a.getValue() 
    .then(function(data){ 
     expect(data).toEqual(data) 
     done(); 
    }) 
    $scope.$apply(); 
}) 

回答

3

這引發消化週期。

docs

測試時的承諾,它知道的 承諾的分辨率是聯繫在一起的消化週期是非常重要的。這意味着一個承諾,然後 捕獲和最終回調函數僅在摘要 已運行後調用。在測試中,您可以通過調用示波器的 $ apply函數來觸發摘要。如果您的測試中沒有示波器,您可以通過 注入$ rootScope並在其上調用$ apply。

對於http調用,您使用$ httpBackend.flush()。從docs

的$ httpBackend在生產中使用總是響應異步請求 。如果我們在單元測試中保留了這種行爲,我們 必須創建難以編寫的異步單元測試,以跟蹤 並進行維護。但是測試模擬也不能同步響應 ;這將改變被測代碼的執行。 因此,模擬$ httpBackend有一個flush()方法,該方法允許測試顯式刷新掛起的請求。這保留了 後端的異步api,同時允許測試同步執行 。

+0

感謝您的回答@scott 您能否詳細說明爲什麼承諾要求在我沒有更改範圍上的任何內容時運行摘要循環。 –

+0

從這個[post](http://blog.xebia.com/testing-promises-in-angularjs/):當一個承諾解決了,它的回調不立即被調用。相反,Angular將promise.resolve回調放在evalAsync隊列中。他們在那裏等待隊列將被處理。只有這樣纔會調用回調。它是處理隊列的digest()方法。 – ScottL