Gibt es da draußen Bibliotheken zum Verspotten localStorage
?
Ich habe Sinon.JS für die meisten meiner anderen Javascript-Verspottungen verwendet und festgestellt, dass es wirklich großartig ist.
Meine ersten Tests haben gezeigt, dass localStorage sich weigert, in Firefox (sadface) zuweisbar zu sein, daher brauche ich wahrscheinlich eine Art Hack, um dies zu umgehen: /
Meine Optionen sind ab sofort (wie ich sehe) wie folgt:
- Erstellen Sie Wrapping-Funktionen, die mein gesamter Code verwendet, und verspotten Sie diese
- Erstellen Sie für localStorage eine Art (möglicherweise kompliziertes) Statusmanagement (Snapshot localStorage vor dem Test, im Bereinigungs-Wiederherstellungs-Snapshot).
??????
Was halten Sie von diesen Ansätzen und glauben Sie, dass es andere bessere Möglichkeiten gibt, dies zu tun? In jedem Fall werde ich die resultierende "Bibliothek", die ich am Ende mache, für Open Source-Güte auf Github stellen.
javascript
unit-testing
mocking
local-storage
sinon
Anthony Sottile
quelle
quelle
Profit!
Antworten:
Hier ist eine einfache Möglichkeit, es mit Jasmine zu verspotten:
Wenn Sie den lokalen Speicher in all Ihren Tests verspotten möchten, deklarieren Sie die
beforeEach()
oben gezeigte Funktion im globalen Bereich Ihrer Tests (der übliche Ort ist ein specHelper.js- Skript).quelle
ReferenceError: localStorage is not defined
(laufende Tests mit FB Jest und npm)… irgendwelche Ideen, wie man das umgeht?window.localStorage
andCallFake
geändert zuand.callFake
in Jasmin 2. +Verspotten Sie einfach den globalen localStorage / sessionStorage (sie haben dieselbe API) für Ihre Anforderungen.
Beispielsweise:
Und was Sie dann tatsächlich tun, ist so etwas:
quelle
getItem
muss zurückgegeben werden,null
wenn kein Wert vorhanden ist :return storage[key] || null;
;localStorage
als Ganzes ist nicht möglich.storage[key] || null
das falsch ist. Wennstorage[key] === 0
esnull
stattdessen zurückkehren wird. Ich denke du könntest es aber tunreturn 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
Wie kann ich das beheben?Berücksichtigen Sie auch die Option, Abhängigkeiten in die Konstruktorfunktion eines Objekts einzufügen.
Im Einklang mit Verspottungen und Unit-Tests möchte ich das Testen der Speicherimplementierung vermeiden. Zum Beispiel macht es keinen Sinn zu überprüfen, ob sich die Speicherlänge nach dem Festlegen eines Elements usw. erhöht hat.
Da es offensichtlich unzuverlässig ist, Methoden für das reale localStorage-Objekt zu ersetzen, verwenden Sie einen "dummen" mockStorage und stubben Sie die einzelnen Methoden wie gewünscht, z.
quelle
Das ist was ich mache...
quelle
Die aktuellen Lösungen funktionieren in Firefox nicht. Dies liegt daran, dass localStorage in der HTML-Spezifikation als nicht änderbar definiert ist. Sie können dies jedoch umgehen, indem Sie direkt auf den Prototyp von localStorage zugreifen.
Die Cross-Browser-Lösung besteht darin, die Objekte
Storage.prototype
zanstelle von spyOn (localStorage, 'setItem') verwenden
entnommen aus den Antworten von bzbarsky und teogeos hier https://github.com/jasmine/jasmine/issues/299
quelle
Ich habe gerade einen geschrieben:
Nur im globalen Kontext. Mit einer Wrapper-Funktion wie oben funktioniert es einwandfrei.
quelle
var window = { localStorage: ... }
localStorage
ja , die Tests sind Testcode, der verwendet wird , die Tests müssen nicht unbedingtlocalStorage
direkt in ihnen enthalten sein. Diese Lösung ändert nichtslocalStorage
für andere Skripte, sodass es sich nicht um eine Lösung handelt. +1 für den Scoping-Trickif this.hasOwnProperty(key) return this[key] else return null
Hier ist ein Beispiel mit Sinon Spy und Mock:
quelle
Das Überschreiben der
localStorage
Eigenschaft des globalenwindow
Objekts, wie in einigen Antworten vorgeschlagen, funktioniert in den meisten JS-Engines nicht, da dielocalStorage
Dateneigenschaft als nicht beschreibbar und nicht konfigurierbar deklariert wird .Ich fand jedoch heraus, dass Sie zumindest mit der WebKit-Version von PhantomJS (Version 1.9.8) die Legacy-API verwenden können, um
__defineGetter__
zu steuern, was passiert, wenn auf sielocalStorage
zugegriffen wird. Trotzdem wäre es interessant, wenn dies auch in anderen Browsern funktioniert.Der Vorteil dieses Ansatzes besteht darin, dass Sie den zu testenden Code nicht ändern müssen.
quelle
Sie müssen das Speicherobjekt nicht an jede Methode übergeben, die es verwendet. Stattdessen können Sie einen Konfigurationsparameter für jedes Modul verwenden, das den Speicheradapter berührt.
Dein altes Modul
Ihr neues Modul mit Konfigurationsfunktion "Wrapper"
Wenn Sie das Modul zum Testen von Code verwenden
Die
MockStorage
Klasse könnte so aussehenWenn Sie Ihr Modul im Produktionscode verwenden, übergeben Sie stattdessen den echten localStorage-Adapter
quelle
export default function
und ein Modul mit einem solchen Argument zu initialisieren, ist nur es6. Das Muster steht trotzdem.require
, um ein Modul zu importieren und es auf ein Argument im selben Ausdruck anzuwenden. In ES6 gibt es keine Möglichkeit, das zu tun, von der ich weiß. Sonst hätte ich ES6 verwendetimport
Ich habe beschlossen, meinen Kommentar zur Antwort von Pumbaa80 als separate Antwort zu wiederholen, damit es einfacher ist, ihn als Bibliothek wiederzuverwenden.
Ich nahm den Code von Pumbaa80, verfeinerte ihn ein wenig, fügte Tests hinzu und veröffentlichte ihn hier als npm-Modul: https://www.npmjs.com/package/mock-local-storage .
Hier ist ein Quellcode: https://github.com/letsrock-today/mock-local-storage/blob/master/src/mock-localstorage.js
Einige Tests: https://github.com/letsrock-today/mock-local-storage/blob/master/test/mock-localstorage.js
Das Modul erstellt Mock LocalStorage und SessionStorage für das globale Objekt (Fenster oder global, welches davon definiert ist).
In den Tests meines anderen Projekts habe ich es mit Mokka wie folgt benötigt:
mocha -r mock-local-storage
um globale Definitionen für den gesamten getesteten Code verfügbar zu machen.Grundsätzlich sieht Code wie folgt aus:
Beachten Sie, dass alle Methoden, die über hinzugefügt wurden,
Object.defineProperty
damit sie nicht als reguläre Elemente iteriert, aufgerufen oder entfernt werden und nicht in der Länge zählen. Außerdem habe ich eine Möglichkeit hinzugefügt, einen Rückruf zu registrieren, der aufgerufen wird, wenn ein Element in ein Objekt eingefügt werden soll. Dieser Rückruf kann verwendet werden, um einen Fehler zu emulieren, bei dem das Kontingent überschritten wurde.quelle
Ich stellte fest, dass ich mich nicht darüber lustig machen musste. Ich könnte den tatsächlichen lokalen Speicher in den Status ändern, über den ich ihn haben möchte
setItem
, und dann einfach die Werte abfragen, um festzustellen, ob er sich über geändert hatgetItem
. Es ist nicht ganz so mächtig wie spöttisch, da man nicht sehen kann, wie oft etwas geändert wurde, aber es hat für meine Zwecke funktioniert.quelle
Leider können wir das localStorage-Objekt in einem Testszenario nur verspotten, indem wir den Code ändern, den wir testen. Sie müssen Ihren Code in eine anonyme Funktion einschließen (was Sie sowieso tun sollten) und "Abhängigkeitsinjektion" verwenden, um einen Verweis auf das Fensterobjekt zu übergeben. Etwas wie:
Innerhalb Ihres Tests können Sie dann Folgendes angeben:
quelle
So mache ich es gerne. Hält es einfach.
quelle
Credits an https://medium.com/@armno/til-mocking-localstorage-and-sessionstorage-in-angular-unit-tests-a765abdc9d87 Machen Sie einen gefälschten lokalen Speicher und spionieren Sie den lokalen Speicher aus, wenn er gespeichert ist
Und hier benutzen wir es
quelle