在Jest测试中,我一直得到“localStorage is not defined”,这是有意义的,但我的选项是什么?碰壁。


当前回答

如果你正在寻找一个mock而不是存根,这是我使用的解决方案:

export const localStorageMock = {
   getItem: jest.fn().mockImplementation(key => localStorageItems[key]),
   setItem: jest.fn().mockImplementation((key, value) => {
       localStorageItems[key] = value;
   }),
   clear: jest.fn().mockImplementation(() => {
       localStorageItems = {};
   }),
   removeItem: jest.fn().mockImplementation((key) => {
       localStorageItems[key] = undefined;
   }),
};

export let localStorageItems = {}; // eslint-disable-line import/no-mutable-exports

为了便于初始化,我导出了存储项。例如,我可以很容易地将它设置为一个对象

在Jest + JSDom的新版本中,不可能设置这个,但是本地存储已经可用,你可以像这样监视它:

const setItemSpy = jest.spyOn(Object.getPrototypeOf(window.localStorage), 'setItem');

其他回答

正如@ck4所建议的那样,文档已经清楚地解释了如何使用localStorage。然而,模拟函数无法执行任何localStorage方法。

下面是我的react组件的详细示例,它使用抽象方法来写入和读取数据,

//file: storage.js
const key = 'ABC';
export function readFromStore (){
    return JSON.parse(localStorage.getItem(key));
}
export function saveToStore (value) {
    localStorage.setItem(key, JSON.stringify(value));
}

export default { readFromStore, saveToStore };

错误:

TypeError: _setupLocalStorage2.default.setItem is not a function

解决办法: 为jest添加以下mock函数(路径:.jest/mocks/setUpStore.js)

let mockStorage = {};

module.exports = window.localStorage = {
  setItem: (key, val) => Object.assign(mockStorage, {[key]: val}),
  getItem: (key) => mockStorage[key],
  clear: () => mockStorage = {}
};

Snippet从这里引用

如果你正在寻找一个mock而不是存根,这是我使用的解决方案:

export const localStorageMock = {
   getItem: jest.fn().mockImplementation(key => localStorageItems[key]),
   setItem: jest.fn().mockImplementation((key, value) => {
       localStorageItems[key] = value;
   }),
   clear: jest.fn().mockImplementation(() => {
       localStorageItems = {};
   }),
   removeItem: jest.fn().mockImplementation((key) => {
       localStorageItems[key] = undefined;
   }),
};

export let localStorageItems = {}; // eslint-disable-line import/no-mutable-exports

为了便于初始化,我导出了存储项。例如,我可以很容易地将它设置为一个对象

在Jest + JSDom的新版本中,不可能设置这个,但是本地存储已经可用,你可以像这样监视它:

const setItemSpy = jest.spyOn(Object.getPrototypeOf(window.localStorage), 'setItem');

至少到目前为止,localStorage可以很容易地在你的笑话测试中被监视,例如:

const spyRemoveItem = jest.spyOn(window.localStorage, 'removeItem')

就是这样。你可以像以前一样使用你的间谍。

正如Niket Pathak在评论中提到的, 从jest@24 / jsdom@11.12.0及以上开始,localStorage将自动被模拟。

在这里引用了一些其他的答案来解决一个用Typescript的项目。我像这样创建了一个LocalStorageMock:

export class LocalStorageMock {

    private store = {}

    clear() {
        this.store = {}
    }

    getItem(key: string) {
        return this.store[key] || null
    }

    setItem(key: string, value: string) {
        this.store[key] = value
    }

    removeItem(key: string) {
        delete this.store[key]
    }
}

然后我创建了一个LocalStorageWrapper类,我使用它来访问应用程序中的所有本地存储,而不是直接访问全局本地存储变量。便于在包装器中为测试设置模拟。