¿Hay bibliotecas para burlarse localStorage
?
He estado usando Sinon.JS para la mayoría de mis otras simulaciones de JavaScript y he descubierto que es realmente genial.
Mi prueba inicial muestra que localStorage se niega a ser asignable en firefox (cara triste), por lo que probablemente necesite algún tipo de truco para esto: /
Mis opciones a partir de ahora (como veo) son las siguientes:
- Crear funciones de envoltura que usa todo mi código y simularlas
- Cree algún tipo de administración estatal (podría ser complicado) (instantánea localStorage antes de la prueba, en instantánea de restauración de limpieza) para localStorage.
??????
¿Qué opinas de estos enfoques y crees que hay otras formas mejores de hacerlo? De cualquier manera, pondré la "biblioteca" resultante que termino haciendo en github para la bondad del código abierto.
javascript
unit-testing
mocking
local-storage
sinon
Anthony Sottile
fuente
fuente
Profit!
Respuestas:
Aquí hay una forma sencilla de burlarse de ella con Jasmine:
Si desea simular el almacenamiento local en todas sus pruebas, declare la
beforeEach()
función que se muestra arriba en el alcance global de sus pruebas (el lugar habitual es un script specHelper.js ).fuente
ReferenceError: localStorage is not defined
(ejecutando pruebas usando FB Jest y npm)… ¿alguna idea de cómo solucionarlo?window.localStorage
andCallFake
cambiado aand.callFake
en jazmín 2. +simplemente simule el localStorage / sessionStorage global (tienen la misma API) para sus necesidades.
Por ejemplo:
Y luego, lo que realmente haces es algo así:
fuente
getItem
debe regresarnull
cuando el valor no existereturn storage[key] || null;
:;localStorage
no es posible anular en su conjunto.storage[key] || null
es incorrecto. Sistorage[key] === 0
volverá en sunull
lugar. Aunque creo que podrías hacerloreturn 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
, ¿alguna idea de cómo puedo solucionarlo?También considere la opción de inyectar dependencias en la función constructora de un objeto.
De acuerdo con las simulaciones y las pruebas unitarias, me gusta evitar probar la implementación del almacenamiento. Por ejemplo, no tiene sentido verificar si la duración del almacenamiento aumentó después de configurar un elemento, etc.
Dado que obviamente no es confiable reemplazar métodos en el objeto localStorage real, use un mockStorage "tonto" y apunte los métodos individuales como desee, como:
fuente
Esto es lo que hago...
fuente
Las soluciones actuales no funcionarán en Firefox. Esto se debe a que localStorage está definido por la especificación html como no modificable. Sin embargo, puede evitar esto accediendo directamente al prototipo de localStorage.
La solución de navegador cruzado es burlarse de los objetos en
Storage.prototype
por ejemplo,en lugar de spyOn (localStorage, 'setItem') use
tomado de las respuestas de bzbarsky y teogeos aquí https://github.com/jasmine/jasmine/issues/299
fuente
Acabo de escribir uno:
Solo en contexto global. Con una función de envoltura como la anterior, funciona bien.
fuente
var window = { localStorage: ... }
localStorage
, las pruebas no necesariamente tienenlocalStorage
directamente en ellas. Esta solución no cambia lalocalStorage
de otros scripts, por lo que no es una solución. Sin embargoif this.hasOwnProperty(key) return this[key] else return null
Aquí hay un ejemplo usando sinon spy and mock:
fuente
Sobrescribir la
localStorage
propiedad delwindow
objeto global como se sugiere en algunas de las respuestas no funcionará en la mayoría de los motores JS, porque declaran que lalocalStorage
propiedad de datos no se puede escribir y no se puede configurar.Sin embargo, descubrí que al menos con la versión de WebKit de PhantomJS (versión 1.9.8) se puede usar la API heredada
__defineGetter__
para controlar lo que sucede silocalStorage
se accede. Aún así, sería interesante si esto también funciona en otros navegadores.El beneficio de este enfoque es que no tendría que modificar el código que está a punto de probar.
fuente
No es necesario que pase el objeto de almacenamiento a cada método que lo utilice. En su lugar, puede utilizar un parámetro de configuración para cualquier módulo que toque el adaptador de almacenamiento.
Tu antiguo módulo
Su nuevo módulo con la función "envoltorio" de configuración
Cuando usa el módulo en código de prueba
La
MockStorage
clase podría verse asíCuando use su módulo en el código de producción, en su lugar pase el adaptador localStorage real
fuente
export default function
e inicializar un módulo con un argumento como ese es solo es6. el patrón se mantiene independientemente.require
para importar un módulo y aplicarlo a un argumento en la misma expresión. No hay forma de hacer eso en ES6 que yo sepa. De lo contrario, habría usado ES6import
Decidí reiterar mi comentario a la respuesta de Pumbaa80 como una respuesta separada para que sea más fácil reutilizarlo como biblioteca.
Tomé el código de Pumbaa80, lo refiné un poco, agregué pruebas y lo publiqué como un módulo npm aquí: https://www.npmjs.com/package/mock-local-storage .
Aquí hay un código fuente: https://github.com/letsrock-today/mock-local-storage/blob/master/src/mock-localstorage.js
Algunas pruebas: https://github.com/letsrock-today/mock-local-storage/blob/master/test/mock-localstorage.js
El módulo crea simulacro de almacenamiento local y almacenamiento de sesión en el objeto global (ventana o global, cuál de ellos está definido).
En las pruebas de mi otro proyecto lo requería con mocha como este:
mocha -r mock-local-storage
hacer que las definiciones globales estén disponibles para todo el código bajo prueba.Básicamente, el código tiene el siguiente aspecto:
Tenga en cuenta que todos los métodos agregados mediante
Object.defineProperty
para que no se repitan, accedan o eliminen como elementos normales y no cuenten en longitud. También agregué una forma de registrar la devolución de llamada que se llama cuando un elemento está a punto de colocarse en un objeto. Esta devolución de llamada se puede utilizar para emular el error de superación de la cuota en las pruebas.fuente
Descubrí que no necesitaba burlarme de él. Podría cambiar el almacenamiento local real al estado en el que lo quería
setItem
, luego simplemente consultar los valores para ver si cambió a través degetItem
. No es tan poderoso como burlón, ya que no puedes ver cuántas veces se cambió algo, pero funcionó para mis propósitos.fuente
Desafortunadamente, la única forma en que podemos burlarnos del objeto localStorage en un escenario de prueba es cambiar el código que estamos probando. Tienes que envolver tu código en una función anónima (que deberías estar haciendo de todos modos) y usar "inyección de dependencia" para pasar una referencia al objeto de la ventana. Algo como:
Luego, dentro de su prueba, puede especificar:
fuente
Así es como me gusta hacerlo. Lo mantiene simple.
fuente
créditos a https://medium.com/@armno/til-mocking-localstorage-and-sessionstorage-in-angular-unit-tests-a765abdc9d87 Haga un almacenamiento local falso y espíe el almacenamiento local, cuando sea caleld
Y aqui lo usamos
fuente