Czy są jakieś biblioteki, z których można kpić localStorage
?
Używam Sinon.JS przez większość mojego innego kpin JavaScript i odkryli, że jest naprawdę świetny.
Moje wstępne testy pokazują, że localStorage odmawia przypisania w Firefoksie (sadface), więc prawdopodobnie będę potrzebował jakiegoś hacka wokół tego: /
Moje opcje na razie (jak widzę) są następujące:
- Twórz funkcje opakowujące, których używa cały mój kod i mockuj je
- Utwórz jakiś rodzaj (może być skomplikowany) zarządzania stanem (migawka localStorage przed testem, w migawce przywracania czyszczenia) dla localStorage.
??????
Co myślisz o tych podejściach i czy uważasz, że są inne lepsze sposoby, aby to osiągnąć? Tak czy inaczej, umieszczę wynikową „bibliotekę”, którą ostatecznie utworzę na githubie dla dobroci open source.
javascript
unit-testing
mocking
local-storage
sinon
Anthony Sottile
źródło
źródło
Profit!
Odpowiedzi:
Oto prosty sposób na kpiny z Jasmine:
Jeśli chcesz mockować pamięć lokalną we wszystkich swoich testach, zadeklaruj
beforeEach()
funkcję pokazaną powyżej w globalnym zakresie testów (zwykle jest to skrypt specHelper.js ).źródło
ReferenceError: localStorage is not defined
(uruchomienie testów przy użyciu FB Jest i npm)… jakieś pomysły jak obejść?window.localStorage
andCallFake
zmieniono naand.callFake
jaśmin 2. +po prostu mock globalny localStorage / sessionStorage (mają to samo API) dla twoich potrzeb.
Na przykład:
A potem to, co faktycznie robisz, jest takie:
źródło
getItem
musi zostać zwrócona,null
gdy wartość nie istniejereturn storage[key] || null;
:;localStorage
jako całość nie jest możliwe.storage[key] || null
to nieprawda. Jeśli zamiast tegostorage[key] === 0
wrócinull
. Myślę, że mógłbyś to zrobić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
jakiś pomysł, jak to naprawić?Rozważ także opcję wstrzyknięcia zależności w funkcji konstruktora obiektu.
Zgodnie z mockingiem i testowaniem jednostkowym wolę unikać testowania implementacji pamięci masowej. Na przykład nie ma sensu sprawdzać, czy długość przechowywania wzrosła po ustawieniu przedmiotu itp.
Ponieważ zastąpienie metod w rzeczywistym obiekcie localStorage jest oczywiście zawodne, użyj „głupiego” mockStorage i odetnij poszczególne metody zgodnie z potrzebami, na przykład:
źródło
Tym się właśnie zajmuję...
źródło
Obecne rozwiązania nie będą działać w przeglądarce Firefox. Dzieje się tak, ponieważ localStorage jest zdefiniowane w specyfikacji HTML jako niemodyfikowalne. Możesz jednak obejść ten problem, uzyskując bezpośredni dostęp do prototypu localStorage.
Rozwiązaniem cross-browser jest mockowanie obiektów
Storage.prototype
npzamiast spyOn (localStorage, 'setItem') użyj
zaczerpnięte z odpowiedzi bzbarsky'ego i teogeosa tutaj https://github.com/jasmine/jasmine/issues/299
źródło
Właśnie napisałem jeden:
Tylko w kontekście globalnym. Z funkcją owijania, jak powyżej, działa dobrze.
źródło
var window = { localStorage: ... }
localStorage
, a testy niekoniecznie mająlocalStorage
w sobie bezpośrednio. To rozwiązanie nie zmienialocalStorage
dla innych skryptów, więc nie jest rozwiązaniem. Jednak +1 dla sztuczki z celownikiemif this.hasOwnProperty(key) return this[key] else return null
Oto przykład użycia Sinon Spy and Mock:
źródło
Nadpisywanie
localStorage
właściwościwindow
obiektu globalnego, jak sugerowano w niektórych odpowiedziach, nie zadziała w większości silników JS, ponieważ deklarują onelocalStorage
właściwość data jako niepisywalną i konfigurowalną.Jednak dowiedziałem się, że przynajmniej z wersją WebKit PhantomJS (wersja 1.9.8) można użyć starszego interfejsu API,
__defineGetter__
aby kontrolować, co się stanie, jeślilocalStorage
zostanie uzyskany dostęp. Mimo to byłoby interesujące, gdyby to działało również w innych przeglądarkach.Zaletą tego podejścia jest to, że nie musisz modyfikować kodu, który zamierzasz przetestować.
źródło
Nie musisz przekazywać obiektu pamięci do każdej metody, która go używa. Zamiast tego można użyć parametru konfiguracyjnego dla dowolnego modułu, który dotyka adaptera pamięci masowej.
Twój stary moduł
Twój nowy moduł z funkcją „wrapper” config
Kiedy używasz modułu w testowaniu kodu
MockStorage
Klasa może wyglądać następującoGdy używasz modułu w kodzie produkcyjnym, zamiast tego przekaż prawdziwy adapter localStorage
źródło
export default function
i zainicjować moduł za pomocą takiego argumentu jak es6. wzór stoi niezależnie.require
aby zaimportować moduł i zastosować go do argumentu w tym samym wyrażeniu. Nie ma sposobu, aby to zrobić w ES6, o którym wiem. W przeciwnym razie użyłbym ES6import
Postanowiłem powtórzyć mój komentarz do odpowiedzi Pumby80 jako oddzielnej odpowiedzi, aby łatwiej było ponownie wykorzystać ją jako bibliotekę.
Wziąłem kod Pumba80, nieco go dopracowałem, dodałem testy i opublikowałem jako moduł npm tutaj: https://www.npmjs.com/package/mock-local-storage .
Oto kod źródłowy: https://github.com/letsrock-today/mock-local-storage/blob/master/src/mock-localstorage.js
Niektóre testy: https://github.com/letsrock-today/mock-local-storage/blob/master/test/mock-localstorage.js
Moduł tworzy mock localStorage i sessionStorage na obiekcie globalnym (window lub global, który z nich jest zdefiniowany).
W testach mojego innego projektu wymagałem tego z mokką w ten sposób:
mocha -r mock-local-storage
aby globalne definicje były dostępne dla całego testowanego kodu.Zasadniczo kod wygląda następująco:
Zwróć uwagę, że wszystkie metody dodane za pośrednictwem,
Object.defineProperty
aby nie były iterowane, otwierane ani usuwane jako zwykłe elementy i nie były liczone w długości. Dodałem również sposób rejestrowania wywołania zwrotnego, które jest wywoływane, gdy przedmiot ma zostać umieszczony w obiekcie. To wywołanie zwrotne może służyć do emulacji błędu przekroczenia limitu w testach.źródło
Okazało się, że nie muszę z tego kpić. Mogłem zmienić rzeczywistą lokalną pamięć masową na stan, przez który chciałem
setItem
, a następnie po prostu zapytać o wartości, aby sprawdzić, czy zmieniły się za pośrednictwemgetItem
. To nie jest tak potężne, jak kpiny, ponieważ nie widać, ile razy coś zostało zmienione, ale zadziałało dla moich celów.źródło
Niestety, jedynym sposobem, w jaki możemy mockować obiekt localStorage w scenariuszu testowym, jest zmiana testowanego kodu. Musisz opakować swój kod w anonimową funkcję (co i tak powinieneś zrobić) i użyć „iniekcji zależności”, aby przekazać referencję do obiektu window. Coś jak:
Następnie w trakcie testu możesz określić:
źródło
Tak lubię to robić. To proste.
źródło
kredyty dla https://medium.com/@armno/til-mocking-localstorage-and-sessionstorage-in-angular-unit-tests-a765abdc9d87 Zrób fałszywy lokalny magazyn i szpieguj w lokalnym magazynie, gdy jest potrzebny
I tutaj go używamy
źródło