如何在JavaScript单元测试中模拟localStorage?

有没有图书馆可以嘲笑?localStorage

我一直在使用Sinon.JS用于我大部分的其他javascript嘲笑,并发现它真的很棒。

我最初的测试表明,localStorage拒绝在firefox(sadface)中分配,所以我可能需要一些技巧来解决这个问题:/

截至目前,我的选项(如我所见)如下:

  1. 创建我所有代码都使用的包装函数并模拟这些函数
  2. 为 localStorage 创建某种(可能很复杂)状态管理(测试前的快照 localStorage,在清理还原快照中)。
  3. ??????

您如何看待这些方法,您认为还有其他更好的方法可以做到这一点吗?无论哪种方式,我都会把我最终在github上制作的最终“库”放在开源上。


答案 1

这是用茉莉花嘲笑它的简单方法:

let localStore;

beforeEach(() => {
  localStore = {};

  spyOn(window.localStorage, 'getItem').and.callFake((key) =>
    key in localStore ? localStore[key] : null
  );
  spyOn(window.localStorage, 'setItem').and.callFake(
    (key, value) => (localStore[key] = value + '')
  );
  spyOn(window.localStorage, 'clear').and.callFake(() => (localStore = {}));
});

如果要在所有测试中模拟本地存储,请在测试的全局范围内声明上面显示的函数(通常的位置是 specHelper.js脚本)。beforeEach()


答案 2

只需模拟全局本地存储/会话存储(它们具有相同的API)即可满足您的需求。
例如:

 // Storage Mock
  function storageMock() {
    let storage = {};

    return {
      setItem: function(key, value) {
        storage[key] = value || '';
      },
      getItem: function(key) {
        return key in storage ? storage[key] : null;
      },
      removeItem: function(key) {
        delete storage[key];
      },
      get length() {
        return Object.keys(storage).length;
      },
      key: function(i) {
        const keys = Object.keys(storage);
        return keys[i] || null;
      }
    };
  }

然后你实际做的是这样的:

// mock the localStorage
window.localStorage = storageMock();
// mock the sessionStorage
window.sessionStorage = storageMock();