2016-09-18 67 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