2016-09-18 68 views
1

嗨我有一個Angular服務,使用另一項服務,從本地存儲加載數據在初始化。不能更新茉莉間諜

angular 
    .module('app') 
    .factory('localStorage', function ($window) 
    { 
     if (!$window.localStorage) 
     { 
      // throw Error 
     } 

     return $window.localStorage; 
    }); 

angular 
    .module('app') 
    .factory('session', function (localStorage) 
    { 
     var container = JSON.parse(localStorage.getItem('sessionContainer')); 

     return { 
      getUser: getUser 
     }; 
    }); 

現在我想測試會話服務。

describe('SessionService', function() 
    { 
     var service; 
     var localStorageMock; 

     // Load the module. 
     beforeEach(module('appRegistration')); 

     // Create mocks. 
     beforeEach(function() 
     { 
      logMock = {}; 

      localStorageMock = jasmine.createSpyObj('localStorageServiceMockSpy', ['setItem', 'getItem']); 
      localStorageMock.getItem.and.returnValue('{}'); 

      module(function ($provide) 
      { 
       $provide.value('localStorage', localStorageMock); 
      }); 

      inject(function (_session_) 
      { 
       service = _session_; 
      }); 
     }); 

     it('should call `getItem` on the `localStorageService` service', function() 
     { 
      expect(localStorageMock.getItem).toHaveBeenCalledWith('sessionContainer'); 
     }); 

     describe('getUser method', function() 
     { 
      it('should return an empty object when the user is not set', function() 
      { 
       var result = service.getUser(); 

       expect(result).toEqual({}); 
      }); 

      it('should return the user data', function() 
      { 
       // localStorageMock.getItem.and.returnValue('{"user":{"some":"data"}}'); 

       var result = service.getUser(); 

       expect(result).toEqual({some: 'user data'}); 
      }); 
     }); 

    }); 

正如你可以在should return the user data部分看到的。 我需要一種方法來更新container,所以getUser返回預期的數據。

我試圖更新getItem間諜,但這不起作用。 localStorageMock已經注入session服務,當我想更改間諜。

任何幫助?

回答

2

最簡單的方法就是與嘲笑值的變量是常見的兩種功能範圍:

var getItemValue; 
    beforeEach({ 
     localStorage: { 
     getItem: jasmine.createSpy().and.callFake(function() { 
      return getItemValue; 
     }), 
     setItem: jasmine.createSpy() 
     } 
    }); 

    ... 
     it('should return the user data', function() 
     { 

      getItemValue = '{"user":{"some":"data"}}'; 

      inject(function (_session_) { 
       service = _session_; 
      }); 

      var result = service.getUser(); 

      expect(result).toEqual({some: 'user data'}); 
     }); 

注意inject應從beforeEach移至it所有規格(規格是別t涉及getItemValue可能使用更短的語法,it('...', inject(function (session) { ... })))。

這揭示了服務設計中的缺陷,它使測試不友好。

的解決方案是使container懶惰地評估,所以有時間來模擬它的應用程序用inject自舉後:

.factory('session', function (localStorage) 
{ 
    var containerCache; 

    function getUser() { 
     ... 
     return this.container; 
    } 
    return { 
     get container() { 
      return (containerCache === undefined) 
       ? (containerCache = JSON.parse(localStorage.getItem('sessionContainer'))) 
       : containerCache; 
     }, 
     getUser: getUser 
    }; 
}); 

此外,這使得能夠測試session.container爲好。在這種情況下,localStorageMock.getItem間諜值可能會在需要時重新定義。

+0

簡單的解決方案是完美的。謝謝。 如果您將答案更改爲ES5,您將得到最佳答案 – WitteStier

+0

如果您關於箭頭函數,它們在可讀性方面很好,我將其替換爲正常的例子。 – estus