2015-07-03 68 views
0

我已經得到了具有以下方法(及其他)服務,它返回一個HTTP $承諾

function sessionService($http, serviceRoot) { 
    return { 
     getAvailableDates: function() { 
      return $http.get(serviceRoot + '/session/available_dates'); 
     } 
    }; 
    }; 

    angular.module('app').service('sessionService', ['$http', 'serviceRoot', sessionService]); 

然後另一家工廠將其包裝並緩存/向localStorage添加數據。這返回一個正常的承諾

angular.module('app') 
    .factory('AvailableDates', AvailableDates); 

AvailableDates.$inject = ['sessionService', '$window', '$q']; 

function AvailableDates(sessionService, $window, $q) { 
    var availableDates = []; 

    return { 
     getAvailableDates: getAvailableDates 
    }; 

    function getAvailableDates() { 
     var deferred = $q.defer(); 
     var fromStorage = JSON.parse($window.sessionStorage.getItem('validDates')); 

     if (availableDates.length > 0) { 
      deferred.resolve(availableDates); 
     } else if (fromStorage !== null) { 
      deferred.resolve(fromStorage); 
     } else { 
      sessionService.getAvailableDates() 
       .success(function (result) { 
        availableDates = result; 
        $window.sessionStorage.setItem('validDates', JSON.stringify(availableDates)); 
        deferred.resolve(availableDates); 
       }); 
     } 
     return deferred.promise; 
    } 
} 

這一切工作正常。我的問題是我無法弄清楚如何在嘲笑sessionService的時候測試這個東西。我已經閱讀了所有相關的stackoverflow問題,並嘗試了各種不同的東西,但無濟於事。

這裏是我的測試目前的樣子:

describe('testing AvailableDates factory', function() { 
    var mock, service, rootScope, spy, window, sessionStorageSpy, $q; 
    var dates = [ "2014-09-27", "2014-09-20", "2014-09-13", "2014-09-06", "2014-08-30" ]; 
    var result; 

    beforeEach(module('app')); 

    beforeEach(function() { 
     return angular.mock.inject(function (_sessionService_, _AvailableDates_, _$rootScope_, _$window_, _$q_) { 
      mock = _sessionService_; 
      service = _AvailableDates_; 
      rootScope = _$rootScope_; 
      window = _$window_; 
      $q = _$q_; 
     }); 
    }); 

    beforeEach(inject(function() { 
     // my service under test calls this service method 
     spy = spyOn(mock, 'getAvailableDates').and.callFake(function() { 
      return { 
       success: function() { 
        return [ "2014-09-27", "2014-09-20", "2014-09-13", "2014-09-06", "2014-08-30" ]; 
       }, 
       error: function() { 
        return "error"; 
       } 
      }; 
     }); 

     spyOn(window.sessionStorage, "getItem").and.callThrough(); 
    })); 

    beforeEach(function() { 
     service.getAvailableDates().then(function(data) { 
      result = data; 
      // use done() here?? 
     }); 
    }); 

    it('first call to fetch available dates hits sessionService and returns dates from the service', function() { 
     rootScope.$apply(); // ?? 

     console.log(result); // this is printing undefined 

     expect(spy).toHaveBeenCalled(); // this passes 
     expect(window.sessionStorage.getItem).toHaveBeenCalled(); // this passes 
    }); 
}); 

我已經試過各種東西,但無法弄清楚如何測試AvailableDates.getAvailableDates的結果()調用。當我使用()完成,我得到的錯誤: 超時 - 由jasmine.DEFAULT_TIMEOUT_INTERVAL規定沒有被引用異步回調withing超時(我試過覆蓋這個值,沒有運氣)。

如果我拿出做(),並調用rootScope。$適用()的。然後被調用後,我得到一個未定義的值作爲我的結果。

我在做什麼錯?

+0

不知道,但可能存儲在一個變量的承諾太('thePromise'),然後調用'thePromise.done()',而不是'rootScope。$適用()'在您的測試 – Rhumborl

+0

有()(在我的測試)指的是茉莉花的()完成 http://jasmine.github.io/2.2/introduction.html#section-Asynchronous_Support 我採用了棱角分明的承諾庫$ q HTTPS://docs.angularjs。組織/ API/NG /服務/ $ q 具有那麼()調用,而不是jQuery的有()調用 – JesseDahl

+0

爲了進一步迷惑的東西,角度的$ HTTP庫返回一個特殊的承諾(其中有.success()和。錯誤回調)。 – JesseDahl

回答

2

我看到在你的例子更多的問題。

的主要問題是在模仿成功的定義。成功是一個函數,它具有作爲參數的函數 - 回調函數。當收到數據時調用回調 - 數據作爲第一個參數傳遞。

return { 
    success: function (callback) { 
     callback(dates); 
    } 
}; 

簡化的工作的例子就是在這裏http://plnkr.co/edit/Tj2TZDWPkzjYhsuSM0u3?p=preview

在這個例子中,模擬傳遞與(從ngMock)模塊功能的提供商 - 您可以通過對象與鍵(服務名稱)和值(實現)。該實施將用於注射。

module({ 
     sessionService:sessionServiceMock 
}); 

我認爲測試邏輯應該在一個函數(測試)中,將其分成beforeEach和測試不是一個好的解決方案。測試就是我的榜樣;它更具可讀性,並且有明顯分離的部分 - 安排,行動,斷言。

inject(function (AvailableDates) { 
    AvailableDates.getAvailableDates().then(function(data) { 
     expect(data).toEqual(dates); 
     done(); 
    }); 

    rootScope.$apply(); // promises are resolved/dispatched only on next $digest cycle 

    expect(sessionServiceMock.getAvailableDates).toHaveBeenCalled(); 
    expect(window.sessionStorage.getItem).toHaveBeenCalled(); 
    }); 
+1

jsteúžasné,děkujihttps://33.media.tumblr.com/tumblr_m6lug797ZT1qgz438.gif – JesseDahl

相關問題