jestjs - getitem - localstorage json
¿Cómo trato con localStorage en las pruebas de broma? (12)
Actualmente (enero ''19) localStorage no puede ser burlado o espiado por broma como lo haría normalmente, y como se describe en los documentos de crear-reaccionar-aplicación. Esto se debe a los cambios realizados en jsdom. Puede leer sobre esto aquí https://github.com/facebook/jest/issues/6798 y aquí https://github.com/jsdom/jsdom/issues/2318 .
Como solución alternativa, puede espiar el prototipo en su lugar:
// does not work:
jest.spyOn(localStorage, "setItem");
localStorage.setItem = jest.fn();
// works:
jest.spyOn(window.localStorage.__proto__, ''setItem'');
window.localStorage.__proto__.setItem = jest.fn();
// assertions as usual:
expect(localStorage.setItem).toHaveBeenCalled();
Sigo recibiendo "localStorage no está definido" en las pruebas de Jest, lo que tiene sentido, pero ¿cuáles son mis opciones? Golpear paredes de ladrillo.
Como @ ck4 la
documentation
sugerida tiene una explicación clara para usar
localStorage
en broma.
Sin embargo, las funciones simuladas no pudieron ejecutar ninguno de los métodos
localStorage
.
A continuación se muestra el ejemplo detallado de mi componente de reacción que utiliza métodos abstractos para escribir y leer datos,
//file: storage.js
const key = ''ABC'';
export function readFromStore (){
return JSON.parse(localStorage.getItem(key));
}
export function saveToStore (value) {
localStorage.setItem(key, JSON.stringify(value));
}
export default { readFromStore, saveToStore };
Error:
TypeError: _setupLocalStorage2.default.setItem is not a function
Reparar:
Agregue la siguiente función simulada para jest (ruta:
.jest/mocks/setUpStore.js
)
let mockStorage = {};
module.exports = window.localStorage = {
setItem: (key, val) => Object.assign(mockStorage, {[key]: val}),
getItem: (key) => mockStorage[key],
clear: () => mockStorage = {}
};
Se hace referencia al fragmento desde here
Encontré esta solución de github
describe(''getToken'', () => {
const Auth = new AuthService();
const token = ''eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Ik1yIEpvc2VwaCIsImlkIjoiNWQwYjk1Mzg2NTVhOTQ0ZjA0NjE5ZTA5IiwiZW1haWwiOiJ0cmV2X2pvc0Bob3RtYWlsLmNvbSIsInByb2ZpbGVVc2VybmFtZSI6Ii9tcmpvc2VwaCIsInByb2ZpbGVJbWFnZSI6Ii9Eb3Nlbi10LUdpci1sb29rLWN1dGUtbnVrZWNhdDMxNnMtMzExNzAwNDYtMTI4MC04MDAuanBnIiwiaWF0IjoxNTYyMzE4NDA0LCJleHAiOjE1OTM4NzYwMDR9.YwU15SqHMh1nO51eSa0YsOK-YLlaCx6ijceOKhZfQZc'';
beforeEach(() => {
global.localStorage = jest.fn().mockImplementation(() => {
return {
getItem: jest.fn().mockReturnValue(token)
}
});
});
it(''should get the token from localStorage'', () => {
const result = Auth.getToken();
expect(result).toEqual(token);
});
});
Puede insertar este código en sus SetupTests y debería funcionar bien.
Lo probé en un proyecto con typectipt.
Gran solución de
Sin embargo, usamos la sintaxis ES2015 y sentí que era un poco más limpio escribirlo de esta manera.
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;
La siguiente solución es compatible para pruebas con TypeScript, ESLint, TSLint y Prettier config más estrictos:
{ "proseWrap": "always", "semi": false, "singleQuote": true, "trailingComma": "es5" }
:
var localStorageMock = (function() {
var store = {};
return {
getItem: function(key) {
return store[key] || null;
},
setItem: function(key, value) {
store[key] = value.toString();
},
clear: function() {
store = {};
}
};
})();
Object.defineProperty(window, ''localStorage'', {
value: localStorageMock
});
HT / https://.com/a/51583401/101290 sobre cómo actualizar global.localStorage
Lo descubrí con la ayuda de esto: https://groups.google.com/forum/#!topic/jestjs/9EPhuNWVYTg
Configure un archivo con los siguientes contenidos:
var localStorageMock = (function() {
var store = {};
return {
getItem: function(key) {
return store[key];
},
setItem: function(key, value) {
store[key] = value.toString();
},
clear: function() {
store = {};
},
removeItem: function(key) {
delete store[key];
}
};
})();
Object.defineProperty(window, ''localStorage'', { value: localStorageMock });
Luego agrega la siguiente línea a su package.json bajo sus configuraciones de Jest
"setupTestFrameworkScriptFile":"PATH_TO_YOUR_FILE",
Riffed algunas otras respuestas aquí para resolverlo para un proyecto con Typecript. Creé un LocalStorageMock como este:
export class LocalStorageMock {
private store = {}
clear() {
this.store = {}
}
getItem(key: string) {
return this.store[key] || null
}
setItem(key: string, value: string) {
this.store[key] = value
}
removeItem(key: string) {
delete this.store[key]
}
}
Luego creé una clase LocalStorageWrapper que uso para todo el acceso al almacenamiento local en la aplicación en lugar de acceder directamente a la variable de almacenamiento local global. Facilitó la configuración del simulacro en el contenedor para las pruebas.
Si está buscando un simulacro y no un trozo, aquí está la solución que uso:
export const localStorageMock = {
getItem: jest.fn().mockImplementation(key => localStorageItems[key]),
setItem: jest.fn().mockImplementation((key, value) => {
localStorageItems[key] = value;
}),
clear: jest.fn().mockImplementation(() => {
localStorageItems = {};
}),
removeItem: jest.fn().mockImplementation((key) => {
localStorageItems[key] = undefined;
}),
};
export let localStorageItems = {}; // eslint-disable-line import/no-mutable-exports
Exporto los elementos de almacenamiento para una fácil inicialización. IE puedo configurarlo fácilmente en un objeto
En las versiones más recientes de Jest + JSDom no es posible configurar esto, pero el almacenamiento local ya está disponible y puede espiarlo de esta manera:
const setItemSpy = jest.spyOn(Object.getPrototypeOf(window.localStorage), ''setItem'');
Si usa create-react-app, hay una solución más simple y directa explicada en la documentation .
Crea
src/setupTests.js
y pon esto en él:
const localStorageMock = {
getItem: jest.fn(),
setItem: jest.fn(),
clear: jest.fn()
};
global.localStorage = localStorageMock;
Contribución de Tom Mertz en un comentario a continuación:
Luego puede probar que las funciones de su localStorageMock se usan haciendo algo como
expect(localStorage.getItem).toBeCalledWith(''token'')
// or
expect(localStorage.getItem.mock.calls.length).toBe(1)
dentro de sus pruebas si quería asegurarse de que se llamara. Echa un vistazo a https://facebook.github.io/jest/docs/en/mock-functions.html
Una mejor alternativa que maneja valores
undefined
(no tiene
toString()
) y devuelve
null
si el valor no existe.
Probado esto con
react
v15,
redux
y
redux-auth-wrapper
class LocalStorageMock {
constructor() {
this.store = {}
}
clear() {
this.store = {}
}
getItem(key) {
return this.store[key] || null
}
setItem(key, value) {
this.store[key] = value
}
removeItem(key) {
delete this.store[key]
}
}
global.localStorage = new LocalStorageMock
o simplemente tomas un paquete simulado como este:
https://www.npmjs.com/package/jest-localstorage-mock
no solo maneja la funcionalidad de almacenamiento, sino que también le permite probar si realmente se llamó a la tienda.
class LocalStorageMock {
public store: {
[key: string]: string
}
constructor() {
this.store = {}
}
public clear() {
this.store = {}
}
public getItem(key: string) {
return this.store[key] || undefined
}
public setItem(key: string, value: string) {
this.store[key] = value.toString()
}
public removeItem(key: string) {
delete this.store[key]
}
}
/* tslint:disable-next-line:no-any */
;(global as any).localStorage = new LocalStorageMock()
Cree un simulacro y agréguelo al objeto
global