Y a-t-il des bibliothèques à se moquer localStorage
?
J'ai utilisé Sinon.JS pour la plupart de mes autres moqueries javascript et j'ai trouvé que c'était vraiment génial.
Mes tests initiaux montrent que localStorage refuse d'être assignable dans Firefox (sadface) donc j'aurai probablement besoin d'une sorte de piratage autour de ceci: /
Mes options pour le moment (comme je le vois) sont les suivantes:
- Créer des fonctions d'emballage que tout mon code utilise et se moquer de celles-ci
- Créez une sorte de gestion de l'état (qui peut être compliquée) (instantané localStorage avant le test, dans le nettoyage de l'instantané de restauration) pour localStorage.
??????
Que pensez-vous de ces approches et pensez-vous qu'il existe d'autres moyens plus efficaces pour y parvenir? Quoi qu'il en soit, je mettrai la "bibliothèque" résultante que je finis par créer sur github pour la bonté open source.
javascript
unit-testing
mocking
local-storage
sinon
Anthony Sottile
la source
la source
Profit!
Réponses:
Voici un moyen simple de se moquer de Jasmine:
Si vous souhaitez vous moquer du stockage local dans tous vos tests, déclarez la
beforeEach()
fonction ci-dessus dans la portée globale de vos tests (l'emplacement habituel est un script specHelper.js ).la source
ReferenceError: localStorage is not defined
(en cours d'exécution des tests en utilisant FB Jest et npm)… des idées comment contourner?window.localStorage
andCallFake
changéand.callFake
en jasmin 2. +simulez simplement le localStorage / sessionStorage global (ils ont la même API) pour vos besoins.
Par exemple:
Et puis ce que vous faites réellement, c'est quelque chose comme ça:
la source
getItem
doit retournernull
lorsque la valeur n'existe pas:return storage[key] || null;
;localStorage
dans son ensemble n'est pas possible.storage[key] || null
c'est incorrect. S'ilstorage[key] === 0
reviendra à lanull
place. Je pense que vous pourriez le fairereturn 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
, une idée comment puis-je résoudre ce problème?Envisagez également la possibilité d'injecter des dépendances dans la fonction constructeur d'un objet.
Dans la lignée des moqueries et des tests unitaires, j'aime éviter de tester l'implémentation du stockage. Par exemple, inutile de vérifier si la durée de stockage a augmenté après avoir défini un élément, etc.
Puisqu'il n'est évidemment pas fiable de remplacer les méthodes sur le véritable objet localStorage, utilisez un mockStorage "stupide" et stub les méthodes individuelles comme vous le souhaitez, comme:
la source
C'est ce que je fais...
la source
Les solutions actuelles ne fonctionneront pas dans Firefox. C'est parce que localStorage est défini par la spécification html comme n'étant pas modifiable. Vous pouvez cependant contourner ce problème en accédant directement au prototype de localStorage.
La solution de navigateur croisé consiste à se moquer des objets sur
Storage.prototype
par exempleau lieu de spyOn (localStorage, 'setItem') utilisez
extrait des réponses de bzbarsky et teogeos ici https://github.com/jasmine/jasmine/issues/299
la source
Je viens d'en écrire un:
Uniquement dans un contexte mondial. Avec une fonction wrapper comme ci-dessus, cela fonctionne très bien.
la source
var window = { localStorage: ... }
localStorage
, les tests n'ont pas nécessairementlocalStorage
directement en eux. Cette solution ne modifie pas lelocalStorage
pour les autres scripts, c'est donc une non-solution. +1 pour le tour de rechercheif this.hasOwnProperty(key) return this[key] else return null
Voici un exemple utilisant sinon spy et mock:
la source
L'écrasement de la
localStorage
propriété de l'window
objet global comme suggéré dans certaines des réponses ne fonctionnera pas dans la plupart des moteurs JS, car ils déclarent lalocalStorage
propriété data comme non accessible en écriture et non configurable.Cependant, j'ai découvert qu'au moins avec la version WebKit de PhantomJS (version 1.9.8), vous pouviez utiliser l'ancienne API
__defineGetter__
pour contrôler ce qui se passe en cas d'localStorage
accès. Néanmoins, il serait intéressant que cela fonctionne également dans d'autres navigateurs.L'avantage de cette approche est que vous n'auriez pas à modifier le code que vous êtes sur le point de tester.
la source
Vous n'êtes pas obligé de transmettre l'objet de stockage à chaque méthode qui l'utilise. Au lieu de cela, vous pouvez utiliser un paramètre de configuration pour tout module qui touche l'adaptateur de stockage.
Votre ancien module
Votre nouveau module avec la fonction de configuration "wrapper"
Lorsque vous utilisez le module pour tester le code
La
MockStorage
classe pourrait ressembler à ceciLorsque vous utilisez votre module dans le code de production, passez plutôt l'adaptateur de stockage local réel
la source
export default function
et d'initialiser un module avec un argument comme celui-ci est uniquement es6. le motif se tient indépendamment.require
pour importer un module et l'appliquer à un argument dans la même expression. Il n'y a aucun moyen de faire cela dans ES6 que je sache. Sinon, j'aurais utilisé ES6import
J'ai décidé de réitérer mon commentaire sur la réponse de Pumbaa80 en tant que réponse séparée afin qu'il soit plus facile de le réutiliser comme bibliothèque.
J'ai pris le code de Pumbaa80, je l'ai raffiné un peu, j'ai ajouté des tests et je l'ai publié en tant que module npm ici: https://www.npmjs.com/package/mock-local-storage .
Voici un code source: https://github.com/letsrock-today/mock-local-storage/blob/master/src/mock-localstorage.js
Quelques tests: https://github.com/letsrock-today/mock-local-storage/blob/master/test/mock-localstorage.js
Le module crée un mock localStorage et sessionStorage sur l'objet global (window ou global, lequel d'entre eux est défini).
Dans les tests de mon autre projet, je l'ai exigé avec mocha comme ceci:
mocha -r mock-local-storage
pour rendre les définitions globales disponibles pour tout le code sous test.Fondamentalement, le code ressemble à ceci:
Notez que toutes les méthodes ajoutées via
Object.defineProperty
afin qu'elles ne soient pas répétées, consultées ou supprimées en tant qu'éléments normaux et ne comptent pas dans leur longueur. J'ai également ajouté un moyen d'enregistrer le rappel qui est appelé lorsqu'un élément est sur le point d'être placé dans l'objet. Ce rappel peut être utilisé pour émuler une erreur de dépassement de quota dans les tests.la source
J'ai trouvé que je n'avais pas besoin de m'en moquer. Je pourrais changer le stockage local réel dans l'état où je le voulais
setItem
, puis interroger simplement les valeurs pour voir si cela a changé viagetItem
. Ce n'est pas aussi puissant que moqueur car vous ne pouvez pas voir combien de fois quelque chose a été changé, mais cela a fonctionné pour mes besoins.la source
Malheureusement, la seule façon de se moquer de l'objet localStorage dans un scénario de test est de modifier le code que nous testons. Vous devez envelopper votre code dans une fonction anonyme (ce que vous devriez faire de toute façon) et utiliser "injection de dépendances" pour passer une référence à l'objet window. Quelque chose comme:
Ensuite, à l'intérieur de votre test, vous pouvez spécifier:
la source
C'est comme ça que j'aime le faire. Reste simple.
la source
crédits à https://medium.com/@armno/til-mocking-localstorage-and-sessionstorage-in-angular-unit-tests-a765abdc9d87 Faites un faux stockage local, et espionnez le stockage local, quand il est appelé
Et ici on l'utilise
la source