Ciągle otrzymuję komunikat „localStorage nie jest zdefiniowany” w testach Jest, co ma sens, ale jakie mam opcje? Uderzanie w ceglane ściany.
144
Świetne rozwiązanie od @chiedo
Jednak używamy składni ES2015 i czułem, że pisanie tego w ten sposób było trochę czystsze.
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 + ''
w|| null
, dlatego mój test się nie powiódł, ponieważ w moim teście używałemnot.toBeDefined()
. Rozwiązanie @Chiedo sprawi, że znowu zadziałaRozgryzłem to z pomocą: https://groups.google.com/forum/#!topic/jestjs/9EPhuNWVYTg
Skonfiguruj plik o następującej zawartości:
Następnie dodaj następujący wiersz do pliku package.json w ramach konfiguracji Jest
"setupTestFrameworkScriptFile":"PATH_TO_YOUR_FILE",
źródło
"setupFiles": [...]
działa również. Z opcją array pozwala na rozdzielenie mocków na osobne pliki. Np .:"setupFiles": ["<rootDir>/__mocks__/localStorageMock.js"]
getItem
różni się nieznacznie od wartości zwracanej przez przeglądarkę, jeśli brak danych zostanie ustawiony dla określonego klucza. wywołanie,getItem("foo")
gdy nie jest ustawione, na przykład zwrócinull
w przeglądarce, aleundefined
przez ten próbny - to powodowało niepowodzenie jednego z moich testów. Prostym rozwiązaniem dla mnie był powrótstore[key] || null
wgetItem
funkcjilocalStorage['test'] = '123'; localStorage.getItem('test')
W przypadku korzystania z aplikacji create-react-app istnieje prostsze i bardziej zrozumiałe rozwiązanie opisane w dokumentacji .
Utwórz
src/setupTests.js
i umieść w nim:Wkład Toma Mertza w komentarzu poniżej:
Następnie możesz sprawdzić, czy funkcje localStorageMock są używane, wykonując coś takiego jak
jeśli chcesz się upewnić, że został wywołany. Sprawdź https://facebook.github.io/jest/docs/en/mock-functions.html
źródło
localStorage
czego używasz w swoim kodzie. (jeśli używaszcreate-react-app
i wszystkich automatycznych skryptów, które zapewnia naturalnie)expect(localStorage.getItem).toBeCalledWith('token')
lubexpect(localStorage.getItem.mock.calls.length).toBe(1)
wewnątrz testów, jeśli chcesz się upewnić, że został wywołany. Zajrzyj na facebook.github.io/jest/docs/en/mock-functions.htmllocalStorage
? Czy nie chciałbyś zresetować szpiegów po każdym teście, aby zapobiec „przenikaniu” do innych testów?Obecnie (październik '19) localStorage nie można wyszydzać ani szpiegować żartem, jak to zwykle bywa, jak opisano w dokumentach aplikacji create-react-app. Wynika to ze zmian wprowadzonych w jsdom. Możesz o tym przeczytać w żartach i jsdom issue trackers.
Aby obejść ten problem, możesz zamiast tego szpiegować prototyp:
źródło
jest.spyOn(window.localStorage.__proto__, 'setItem');
lub po prostu bierzesz przykładową paczkę, taką jak ta:
https://www.npmjs.com/package/jest-localstorage-mock
obsługuje nie tylko funkcjonalność magazynu, ale także pozwala przetestować, czy sklep został faktycznie wywołany.
źródło
Lepsza alternatywa, która obsługuje
undefined
wartości (których nie matoString()
) i zwraca,null
jeśli wartość nie istnieje. Przetestowano to wreact
wersji 15redux
iredux-auth-wrapper
źródło
removeItem
: developer.mozilla.org/en-US/docs/Web/API/Storage/removeItemJeśli szukasz makiety a nie stubu, oto rozwiązanie, którego używam:
Eksportuję elementy pamięci w celu łatwej inicjalizacji. IE Mogę łatwo ustawić go na obiekt
W nowszych wersjach Jest + JSDom nie można tego ustawić, ale lokalna pamięć jest już dostępna i można ją szpiegować w następujący sposób:
źródło
Znalazłem to rozwiązanie z github
Możesz wstawić ten kod w swoim setupTests i powinien działać dobrze.
Przetestowałem to w projekcie z typem.
źródło
Niestety rozwiązania, które tu znalazłem, nie zadziałały.
Więc szukałem problemów z Jest GitHub i znalazłem ten wątek
Najbardziej pozytywnymi rozwiązaniami były te:
źródło
window
lub nie sąStorage
zdefiniowane. Może to starsza wersja Jest, której używam.Jak sugerował @ ck4, dokumentacja zawiera jasne wyjaśnienie użycia
localStorage
żartu. Jednak funkcje pozorowane nie mogły wykonać żadnej zlocalStorage
metod.Poniżej znajduje się szczegółowy przykład mojego komponentu reagowania, który wykorzystuje abstrakcyjne metody zapisu i odczytu danych,
Błąd:
Fix:
Dodaj poniżej funkcji makiety jest (dla ścieżki:
.jest/mocks/setUpStore.js
)Odwołanie do fragmentu jest stąd
źródło
Odsunęłam tutaj kilka innych odpowiedzi, aby rozwiązać problem dla projektu za pomocą Typescript. Utworzyłem LocalStorageMock w następujący sposób:
Następnie utworzyłem klasę LocalStorageWrapper, której używam do uzyskiwania dostępu do lokalnej pamięci w aplikacji zamiast bezpośredniego dostępu do globalnej zmiennej lokalnej pamięci. Ułatwiono umieszczenie makiety w opakowaniu do testów.
źródło
Utwórz makietę i dodaj ją do
global
obiektuźródło
Możesz użyć tego podejścia, aby uniknąć kpiny.
źródło
Musisz mockować pamięć lokalną za pomocą tych fragmentów
// localStorage.js
A w żartobliwej konfiguracji:
Nie wahaj się zapytać o wszystko.
źródło
Następujące rozwiązanie jest kompatybilne do testowania z bardziej rygorystyczną konfiguracją TypeScript, ESLint, TSLint i Prettier
{ "proseWrap": "always", "semi": false, "singleQuote": true, "trailingComma": "es5" }
:HT / https://stackoverflow.com/a/51583401/101290, aby dowiedzieć się, jak zaktualizować global.localStorage
źródło
Aby zrobić to samo w skrypcie, wykonaj następujące czynności:
Skonfiguruj plik o następującej zawartości:
Następnie dodaj następujący wiersz do pliku package.json w ramach konfiguracji Jest
"setupTestFrameworkScriptFile":"PATH_TO_YOUR_FILE",
Lub importujesz ten plik w swoim przypadku testowym, w którym chcesz mockować lokalny magazyn.
źródło
To zadziałało dla mnie,
źródło