Я продолжаю получать сообщение «localStorage is not defined» в тестах Jest, что имеет смысл, но каковы мои варианты? Удар по кирпичным стенам.
148
Отличное решение от @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;
value + ''
в инкубаторе с ручкой нуль и неопределенными значениями правильно|| null
именно поэтому мой тест провалился, потому что в моем тесте я использовалnot.toBeDefined()
. Решение @Chiedo заставит его снова работатьРазобрался с помощью этого: 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 });
Затем вы добавляете следующую строку в свой package.json в конфигурациях Jest
"setupTestFrameworkScriptFile":"PATH_TO_YOUR_FILE",
источник
"setupFiles": [...]
тоже работает. С опцией массива позволяет разделять макеты на отдельные файлы. Например:"setupFiles": ["<rootDir>/__mocks__/localStorageMock.js"]
getItem
немного отличается от того, что было бы возвращено браузером, если для определенного ключа не заданы данные. вызов,getItem("foo")
когда он не установлен, например, вернетсяnull
в браузере, но из-undefined
за этого макета - это привело к сбою одного из моих тестов. Простым решением для меня было вернутьсяstore[key] || null
вgetItem
функциюlocalStorage['test'] = '123'; localStorage.getItem('test')
При использовании создания реагирующего-приложения, есть более простое и простое решение описано в документации .
Создайте
src/setupTests.js
и поместите в него:Вклад Тома Мертца в комментарии ниже:
Затем вы можете проверить, используются ли ваши функции localStorageMock, выполнив что-то вроде
внутри ваших тестов, если вы хотите убедиться, что он был вызван. Посетите https://facebook.github.io/jest/docs/en/mock-functions.html
источник
localStorage
вы используете в своем коде. (если вы используетеcreate-react-app
все автоматические скрипты, которые он предоставляет, естественно)expect(localStorage.getItem).toBeCalledWith('token')
илиexpect(localStorage.getItem.mock.calls.length).toBe(1)
внутри ваших тестов, если вы хотите убедиться, что он был вызван. Проверьте facebook.github.io/jest/docs/en/mock-functions.htmllocalStorage
? Разве вы не хотели бы сбрасывать шпионов после каждого теста, чтобы предотвратить «перетекание» в другие тесты?В настоящее время (октябрь '19) localStorage нельзя высмеивать или шпионить с помощью шуток, как это обычно делается и как указано в документации create-response-app. Это связано с изменениями, внесенными в jsdom. Вы можете прочитать об этом в трекерах проблем jest и jsdom .
В качестве обходного пути вы можете вместо этого шпионить за прототипом:
// 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();
источник
jest.spyOn(window.localStorage.__proto__, 'setItem');
Лучшая альтернатива, которая обрабатывает
undefined
значения (у него нетtoString()
) и возвращает,null
если значение не существует. Проверено сreact
v15,redux
иredux-auth-wrapper
источник
removeItem
: developer.mozilla.org/en-US/docs/Web/API/Storage/removeItemили вы просто возьмете такой макет пакета:
https://www.npmjs.com/package/jest-localstorage-mock
он обрабатывает не только функции хранилища, но также позволяет проверить, действительно ли было вызвано хранилище.
источник
Если вы ищете макет, а не заглушку, вот решение, которое я использую:
Я экспортирую элементы хранения для облегчения инициализации. IE я могу легко установить его на объект
В более новых версиях Jest + JSDom это невозможно установить, но локальное хранилище уже доступно, и вы можете следить за ним следующим образом:
источник
К сожалению, решения, которые я здесь нашел, у меня не сработали.
Итак, я смотрел на проблемы Jest GitHub и нашел эту ветку
Наибольшее количество голосов получили следующие решения:
const spy = jest.spyOn(Storage.prototype, 'setItem'); // or Storage.prototype.getItem = jest.fn(() => 'bla');
источник
window
илиStorage
любой. Возможно, я использую старую версию Jest.Я нашел это решение с github
Вы можете вставить этот код в свои setupTests, и он должен работать нормально.
Я тестировал его в проекте с typectipt.
источник
Как @ CK4 предложил документации имеет четкое объяснение для использования
localStorage
в шутке. Однако фиктивные функции не смогли выполнить ни один изlocalStorage
методов.Ниже приведен подробный пример моего реагирующего компонента, который использует абстрактные методы для записи и чтения данных.
Ошибка:
Исправление:
Добавьте ниже макет функции для шутки (пути:
.jest/mocks/setUpStore.js
)Ссылка на фрагмент отсюда
источник
Вы можете использовать этот подход, чтобы избежать насмешек.
источник
Вам нужно имитировать локальное хранилище с помощью этих фрагментов
// localStorage.js
И в конфиге шутки:
Не стесняйтесь спрашивать о чем угодно.
источник
Отказался от некоторых других ответов здесь, чтобы решить эту проблему для проекта с Typescript. Я создал LocalStorageMock следующим образом:
Затем я создал класс LocalStorageWrapper, который использую для всего доступа к локальному хранилищу в приложении вместо прямого доступа к глобальной локальной переменной хранилища. Упростили установку макета в оболочку для тестов.
источник
Создайте макет и добавьте его к
global
объектуисточник
Чтобы сделать то же самое в машинописном тексте, сделайте следующее:
Установите файл со следующим содержимым:
Затем вы добавляете следующую строку в свой package.json в конфигурациях Jest
"setupTestFrameworkScriptFile":"PATH_TO_YOUR_FILE",
Или вы импортируете этот файл в свой тестовый пример, где хотите имитировать локальное хранилище.
источник
Следующее решение совместимо для тестирования с более строгими конфигурациями TypeScript, ESLint, TSLint и Prettier
{ "proseWrap": "always", "semi": false, "singleQuote": true, "trailingComma": "es5" }
:HT / https://stackoverflow.com/a/51583401/101290 о том, как обновить global.localStorage
источник
Это сработало для меня,
источник