2016-09-18 8 views
1

私はinitのローカルストレージからデータをロードする別のサービスを使用するAngularサービスを持っています。cant update jasmine spy

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サービスに挿入されています。

助けが必要ですか?

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は、(すべての仕様のためitbeforeEachからスペックを移動する必要があることに注意してくださいドン」:

答えて

2

最も簡単な方法は、両方の機能のスコープのために共通である嘲笑値を持つ変数を持つことですより短い構文、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