Есть ли какие-нибудь библиотеки, которые можно поиздеваться localStorage
?
Я использую Sinon.JS для большинства других своих издевательств над javascript и обнаружил, что это действительно здорово.
Мое первоначальное тестирование показывает, что localStorage не может быть назначен в firefox (sadface), поэтому мне, вероятно, понадобится какой-то взлом по этому поводу: /
Мои варианты на данный момент (как я вижу) следующие:
- Создавайте функции обертывания, которые использует весь мой код, и имитируйте те
- Создайте какое-то (может быть сложно) управление состоянием (снимок localStorage перед тестом, снимок восстановления после очистки) для localStorage.
??????
Что вы думаете об этих подходах, и как вы думаете, есть ли другие способы сделать это лучше? В любом случае я помещу получившуюся «библиотеку», которую в конечном итоге сделаю, на github для добра с открытым кодом.
javascript
unit-testing
mocking
local-storage
sinon
Энтони Соттиле
источник
источник
Profit!
Ответы:
Вот простой способ поиздеваться над этим с помощью Жасмин:
Если вы хотите имитировать локальное хранилище во всех ваших тестах, объявите
beforeEach()
функцию, показанную выше, в глобальной области ваших тестов (обычно это скрипт specHelper.js ).источник
ReferenceError: localStorage is not defined
(запуск тестов с использованием FB Jest и npm)… есть идеи, как обойтись ?window.localStorage
andCallFake
изменен наand.callFake
жасмин 2. +просто имитируйте глобальный localStorage / sessionStorage (у них одинаковый API) для ваших нужд.
Например:
И тогда вы на самом деле делаете что-то вроде этого:
источник
getItem
должно возвращаться,null
если значение не существуетreturn storage[key] || null;
:;localStorage
в целом невозможно.storage[key] || null
это неверно. Еслиstorage[key] === 0
он вернетсяnull
вместо этого. Я думаю, тыreturn key in storage ? storage[key] : null
справишься.function storageMock() { var 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) { var keys = Object.keys(storage); return keys[i] || null; } }; } window.localStor = storageMock();
TypeError: Cannot set property localStorage of #<Window> which has only a getter
, есть идеи, как это исправить?Также рассмотрите возможность внедрения зависимостей в функцию конструктора объекта.
В соответствии с имитацией и модульным тестированием мне нравится избегать тестирования реализации хранилища. Например, нет смысла проверять, увеличилась ли длина хранилища после того, как вы установили элемент и т. Д.
Поскольку очевидно, что замена методов в реальном объекте localStorage ненадежна, используйте «тупой» mockStorage и при необходимости вставьте отдельные методы в заглушки, например:
источник
Вот что я делаю...
источник
Текущие решения не будут работать в Firefox. Это связано с тем, что localStorage определяется спецификацией html как не подлежащий изменению. Однако вы можете обойти это, обратившись к прототипу localStorage напрямую.
Кроссбраузерное решение - издеваться над объектами,
Storage.prototype
например,вместо spyOn (localStorage, 'setItem') используйте
взято из ответов bzbarsky и teogeos здесь https://github.com/jasmine/jasmine/issues/299
источник
Я только что написал:
Только в глобальном контексте. С функцией-оболочкой, как указано выше, она работает нормально.
источник
var window = { localStorage: ... }
localStorage
, тесты не обязательно содержатlocalStorage
непосредственно в них. Это решение не меняетlocalStorage
других сценариев, поэтому это не решение. +1 за трюк сif this.hasOwnProperty(key) return this[key] else return null
Вот пример использования sinon spy and mock:
источник
Перезапись
localStorage
свойства глобальногоwindow
объекта, как предлагается в некоторых ответах, не будет работать в большинстве движков JS, потому что они объявляютlocalStorage
свойство данных как недоступное для записи и настройки.Однако я обнаружил, что, по крайней мере, с версией WebKit PhantomJS (версия 1.9.8) вы можете использовать устаревший API
__defineGetter__
для управления тем, что происходит, еслиlocalStorage
к нему обращаются. Тем не менее было бы интересно, если бы это работало и в других браузерах.Преимущество этого подхода в том, что вам не придется изменять код, который вы собираетесь тестировать.
источник
Вам не нужно передавать объект хранилища каждому методу, который его использует. Вместо этого вы можете использовать параметр конфигурации для любого модуля, который касается адаптера хранилища.
Ваш старый модуль
Ваш новый модуль с функцией config "wrapper"
Когда вы используете модуль в тестовом коде
MockStorage
Класс может выглядеть следующим образомПри использовании вашего модуля в производственном коде вместо этого передайте реальный адаптер localStorage
источник
export default function
и инициализация модуля с таким аргументом - это только es6. шаблон остается неизменным.require
чтобы импортировать модуль и применить его к аргументу в том же выражении. Я не знаю, как сделать это в ES6. В противном случае я бы использовал ES6import
Я решил повторить свой комментарий к ответу Pumbaa80 как отдельный ответ, чтобы его было легче повторно использовать в качестве библиотеки.
Я взял код Pumbaa80, немного доработал его, добавил тесты и опубликовал его как модуль npm здесь: https://www.npmjs.com/package/mock-local-storage .
Вот исходный код: https://github.com/letsrock-today/mock-local-storage/blob/master/src/mock-localstorage.js
Некоторые тесты: https://github.com/letsrock-today/mock-local-storage/blob/master/test/mock-localstorage.js
Модуль создает mock localStorage и sessionStorage на глобальном объекте (оконном или глобальном, какой из них определен).
В тестах другого моего проекта я требовал этого с мокко следующим образом:
mocha -r mock-local-storage
сделать глобальные определения доступными для всего тестируемого кода.В основном код выглядит следующим образом:
Обратите внимание, что все методы добавлены через,
Object.defineProperty
поэтому они не будут повторяться, использоваться или удаляться как обычные элементы и не учитываются по длине. Также я добавил способ регистрации обратного вызова, который вызывается, когда элемент собирается быть помещенным в объект. Этот обратный вызов может использоваться для имитации ошибки превышения квоты в тестах.источник
Я обнаружил, что мне не нужно издеваться над этим. Я мог бы изменить фактическое локальное хранилище на состояние, которое я хотел
setItem
, а затем просто запросить значения, чтобы увидеть, изменилось ли оно черезgetItem
. Это не так мощно, как насмешка, поскольку вы не можете увидеть, сколько раз что-то менялось, но для моих целей это сработало.источник
К сожалению, единственный способ имитировать объект localStorage в тестовом сценарии - это изменить тестируемый код. Вы должны заключить свой код в анонимную функцию (что вы все равно должны делать) и использовать «внедрение зависимостей» для передачи ссылки на объект окна. Что-то вроде:
Затем внутри вашего теста вы можете указать:
источник
Вот как я люблю это делать. Все просто.
источник
кредиты на https://medium.com/@armno/til-mocking-localstorage-and-sessionstorage-in-angular-unit-tests-a765abdc9d87 Сделайте поддельное локальное хранилище и шпионите за локальным хранилищем, когда оно настроено
И здесь мы его используем
источник