如何对使用localStorage的AngularJS服务进行单元测试

4

我该如何使用Jasmine和ngMock对使用$window.localStorage的工厂进行单元测试?

以下是类似于我的内容:

myApp.factory('myData',function ($window) {
    return { 
        message: $window.localStorage['stuff'] 
    }
});

非常感谢!
2个回答

6
以下内容适用于Jasmine 2.4:
angular.module('MyModule', []).factory('myData',function ($window) {
    return { 
        message: function(){
          return $window.localStorage['stuff'] ;
        }
    }
});

describe("TestName", function() {
  beforeEach(module('MyModule'));
  var myData, store;
  beforeEach(inject(function(_myData_) {
    myData = _myData_;
    store = {};
    var localStorage = window.localStorage;
    spyOn(localStorage, 'getItem').and.callFake(function (key) {
      return store[key];
    });
    spyOn(localStorage, 'setItem').and.callFake(function (key, value) {
      return store[key] = value + '';
    });
    spyOn(localStorage, 'clear').and.callFake(function () {
      store = {};
    });
  }));

  it("feature desc", function() {
    localStorage['stuff'] = 'hello';
    expect(myData.message()).toEqual('hello');
  });
});

注意使用 _myData_ 下划线技巧(参见文档)。


太好了。这个可行。不知道为什么,但我也试图模拟工厂。 - tanmay

3

小小澄清:如果localStorage不包含一个键,这个模拟返回undefined,但是真正的返回值是null

getItem(key)方法必须返回与给定键相关联的当前值。如果该对象关联的列表中不存在给定键,则此方法必须返回null。https://www.w3.org/TR/webstorage/

  spyOn(localStorage, 'getItem').and.callFake(function (key) {
    return store[key] !== undefined ? store[key] : null;
  });

注意:在之前的例子中,方法removeItem没有被模拟。
  spyOn(localStorage, 'removeItem').and.callFake(function (key, value) {
    delete store[key];
  });

顺便说一下,我发现了另一种在本地存储中编写测试的方法,而无需模拟它,也许这是有意义的,因为使用原始数据类型和localStorage可能很棘手。

afterEach(() => {
  localStorage.removeItem(testTokenKey);
});

本地存储在测试之间保持不变。删除本地存储键是防止一个测试对另一个测试产生副作用的好方法。 - piccy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接