我一直在Jest测试中得到"localStorage is not defined",这是有道理的,但我的选择是什么?打砖墙.
小智 130
@chiedo的绝佳解决方案
但是,我们使用ES2015语法,我觉得以这种方式编写它会更清晰.
class LocalStorageMock {
constructor() {
this.store = {};
}
clear() {
this.store = {};
}
getItem(key) {
return this.store[key] || null;
}
setItem(key, value) {
this.store[key] = value.toString();
}
removeItem(key) {
delete this.store[key];
}
};
global.localStorage = new LocalStorageMock;
Run Code Online (Sandbox Code Playgroud)
Chi*_*edo 85
在此帮助下计算出来:https://groups.google.com/forum/#!topic / jestjs/9EPhuNWVYTg
使用以下内容设置文件:
var localStorageMock = (function() {
var store = {};
return {
getItem: function(key) {
return store[key];
},
setItem: function(key, value) {
store[key] = value.toString();
},
clear: function() {
store = {};
},
removeItem: function(key) {
delete store[key];
}
};
})();
Object.defineProperty(window, 'localStorage', { value: localStorageMock });
Run Code Online (Sandbox Code Playgroud)
然后在Jest配置下将以下行添加到package.json中
"setupTestFrameworkScriptFile":"PATH_TO_YOUR_FILE",
c4k*_*c4k 51
如果使用create-react-app,则可以在文档中解释更简单直接的解决方案.
创建src/setupTests.js并将其放入其中:
const localStorageMock = {
getItem: jest.fn(),
setItem: jest.fn(),
clear: jest.fn()
};
global.localStorage = localStorageMock;
Run Code Online (Sandbox Code Playgroud)
Tom Mertz在以下评论中的贡献:
然后,您可以通过执行类似操作来测试您的localStorageMock的函数
expect(localStorage.getItem).toBeCalledWith('token')
// or
expect(localStorage.getItem.mock.calls.length).toBe(1)
Run Code Online (Sandbox Code Playgroud)
如果你想确保它被调用,你的测试内部.查看https://facebook.github.io/jest/docs/en/mock-functions.html
Bas*_*ein 23
目前(Jan '19)localStorage不能像往常那样通过开玩笑来嘲笑或监视,并且如create-react-app docs中所述.这是由于在jsdom中所做的更改.你可以在这里阅读https://github.com/facebook/jest/issues/6798和https://github.com/jsdom/jsdom/issues/2318.
作为一种解决方法,您可以窥探原型:
// does not work:
jest.spyOn(localStorage, "setItem");
localStorage.setItem = jest.fn();
// works:
jest.spyOn(window.localStorage.__proto__, 'setItem');
window.localStorage.__proto__.setItem = jest.fn();
// assertions as usual:
expect(localStorage.setItem).toHaveBeenCalled();
Run Code Online (Sandbox Code Playgroud)
Chr*_*iki 17
不幸的是,我在这里找到的解决方案对我不起作用。
所以我在看 Jest GitHub 问题并找到了这个线程
最受好评的解决方案是这些:
const spy = jest.spyOn(Storage.prototype, 'setItem');
// or
Storage.prototype.getItem = jest.fn(() => 'bla');
Run Code Online (Sandbox Code Playgroud)
Ali*_*tor 13
或者你只是采取这样的模拟包:
https://www.npmjs.com/package/jest-localstorage-mock
它不仅可以处理存储功能,还可以测试是否实际调用了存储.
Dmi*_*riy 12
处理undefined值(它没有toString())的更好的替代方法,null如果值不存在则返回.用reactv15 测试了这个,redux和redux-auth-wrapper
class LocalStorageMock {
constructor() {
this.store = {}
}
clear() {
this.store = {}
}
getItem(key) {
return this.store[key] || null
}
setItem(key, value) {
this.store[key] = value
}
removeItem(key) {
delete this.store[key]
}
}
global.localStorage = new LocalStorageMock
Run Code Online (Sandbox Code Playgroud)
Tig*_*ear 11
如果您正在寻找模拟而不是存根,这是我使用的解决方案:
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
Run Code Online (Sandbox Code Playgroud)
我导出存储项以便于初始化。IE 我可以很容易地将它设置为一个对象
在较新版本的 Jest + JSDom 中,无法设置此项,但是 localstorage 已经可用,您可以像这样监视它:
const setItemSpy = jest.spyOn(Object.getPrototypeOf(window.localStorage), 'setItem');
Run Code Online (Sandbox Code Playgroud)
我从github找到了这个解决方案
var localStorageMock = (function() {
var store = {};
return {
getItem: function(key) {
return store[key] || null;
},
setItem: function(key, value) {
store[key] = value.toString();
},
clear: function() {
store = {};
}
};
})();
Object.defineProperty(window, 'localStorage', {
value: localStorageMock
});
Run Code Online (Sandbox Code Playgroud)
您可以在 setupTests 中插入此代码,它应该可以正常工作。
我在一个带有 typectipt 的项目中对其进行了测试。
使用 TypeScript 和 Jest 的更优雅的解决方案。
\n interface Spies {\n [key: string]: jest.SpyInstance\n }\n \n describe(\'\xe2\x86\x92 Local storage\', () => {\n \n const spies: Spies = {}\n \n beforeEach(() => {\n [\'setItem\', \'getItem\', \'clear\'].forEach((fn: string) => {\n const mock = jest.fn(localStorage[fn])\n spies[fn] = jest.spyOn(Storage.prototype, fn).mockImplementation(mock)\n })\n })\n \n afterEach(() => {\n Object.keys(spies).forEach((key: string) => spies[key].mockRestore())\n })\n \n test(\'\xe2\x86\x92 setItem ...\', async () => {\n localStorage.setItem( \'foo\', \'bar\' )\n expect(localStorage.getItem(\'foo\')).toEqual(\'bar\')\n expect(spies.setItem).toHaveBeenCalledTimes(1)\n })\n })\nRun Code Online (Sandbox Code Playgroud)\n
Object.defineProperty(window, "localStorage", {
value: {
getItem: jest.fn(),
setItem: jest.fn(),
removeItem: jest.fn(),
},
});
Run Code Online (Sandbox Code Playgroud)
或者
jest.spyOn(Object.getPrototypeOf(localStorage), "getItem");
jest.spyOn(Object.getPrototypeOf(localStorage), "setItem");
Run Code Online (Sandbox Code Playgroud)
2022 年更新。
Jest@24+ 能够自动模拟本地存储。但是,默认情况下不再附带所需的依赖项。
npm i -D jest-environment-jsdom
您还需要更改 Jest 测试模式:
// jest.config.cjs
module.exports = {
...
testEnvironment: "jsdom",
...
};
Run Code Online (Sandbox Code Playgroud)
现在 localStorage 已经被你嘲笑了。
例子:
// myStore.js
const saveLocally = (key, value) => {
localStorage.setItem(key, value)
};
Run Code Online (Sandbox Code Playgroud)
测试:
// myStore.spec.ts
import { saveLocally } from "./myStore.js"
it("saves key-value pair", () => {
let key = "myKey";
let value = "myValue";
expect(localStorage.getItem(key)).toBe(null);
saveLocally(key, value);
expect(localStorage.getItem(key)).toBe(value);
};
Run Code Online (Sandbox Code Playgroud)
您可以使用这种方法来避免嘲笑。
Storage.prototype.getItem = jest.fn(() => expectedPayload);
Run Code Online (Sandbox Code Playgroud)
小智 5
您需要使用此代码段模拟本地存储
// 本地存储.js
var localStorageMock = (function() {
var store = {};
return {
getItem: function(key) {
return store[key] || null;
},
setItem: function(key, value) {
store[key] = value.toString();
},
clear: function() {
store = {};
}
};
})();
Object.defineProperty(window, 'localStorage', {
value: localStorageMock
});
Run Code Online (Sandbox Code Playgroud)
在开玩笑的配置中:
"setupFiles":["localStorage.js"]
Run Code Online (Sandbox Code Playgroud)
随意问任何事情。
我想我会在带有 React 的 TypeScript 中添加另一个对我来说非常有效的解决方案:
我创建了一个 mockLocalStorage.ts
export const mockLocalStorage = () => {
const setItemMock = jest.fn();
const getItemMock = jest.fn();
beforeEach(() => {
Storage.prototype.setItem = setItemMock;
Storage.prototype.getItem = getItemMock;
});
afterEach(() => {
setItemMock.mockRestore();
getItemMock.mockRestore();
});
return { setItemMock, getItemMock };
};
Run Code Online (Sandbox Code Playgroud)
我的组件:
export const Component = () => {
const foo = localStorage.getItem('foo')
return <h1>{foo}</h1>
}
Run Code Online (Sandbox Code Playgroud)
然后在我的测试中我像这样使用它:
import React from 'react';
import { mockLocalStorage } from '../../test-utils';
import { Component } from './Component';
const { getItemMock, setItemMock } = mockLocalStorage();
it('fetches something from localStorage', () => {
getItemMock.mockReturnValue('bar');
render(<Component />);
expect(getItemMock).toHaveBeenCalled();
expect(getByText(/bar/i)).toBeInTheDocument()
});
it('expects something to be set in localStorage' () => {
const value = "value"
const key = "key"
render(<Component />);
expect(setItemMock).toHaveBeenCalledWith(key, value);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
48729 次 |
| 最近记录: |