При тестировании компонентов в JavaScript важным аспектом является
работа с локальными хранилищами, такими как localStorage и
sessionStorage. Эти механизмы используются для хранения
данных в браузере и часто встречаются в реальных приложениях. Однако при
написании тестов для компонентов, использующих локальное хранилище,
важно правильно замокать эти объекты, чтобы избежать побочных эффектов,
связанных с реальным взаимодействием с браузером. Enzyme, в сочетании с
Jest, предоставляет эффективные инструменты для мокирования локального
хранилища, что позволяет создать изолированные тесты и повысить
стабильность тестов.
localStorage?Работа с реальным localStorage может привести к
нежелательным побочным эффектам, например, изменению данных, которые
используются другими частями приложения. В процессе тестирования
необходимо изолировать компоненты и убедиться, что данные хранятся и
извлекаются корректно, без влияния на другие тесты или взаимодействия с
браузером.
Мокирование localStorage позволяет:
localStorage в JestВ Jest можно мокировать объекты браузера, такие как
localStorage, с помощью глобальных функций. Для этого нужно
перезаписать методы localStorage, чтобы они использовались
в тестах вместо реальных.
Пример мокирования localStorage с использованием
Jest:
beforeEach(() => {
const localStorageMock = (function() {
let store = {};
return {
getItem: (key) => store[key] || null,
setItem: (key, value) => { store[key] = value.toString(); },
clear: () => { store = {}; },
removeItem: (key) => { delete store[key]; },
};
})();
global.localStorage = localStorageMock;
});
Здесь создается мок-объект localStorageMock, который
имитирует поведение настоящего localStorage, но хранит
данные в памяти, а не в браузере. Используя beforeEach, мы
убеждаемся, что каждый тест будет начинаться с чистого состояния
хранилища.
localStorageДопустим, у нас есть компонент, который сохраняет и загружает данные из локального хранилища. Для его тестирования можно использовать следующий подход:
import React from 'react';
import { mount } from 'enzyme';
import MyComponent from './MyComponent';
describe('MyComponent', () => {
beforeEach(() => {
const localStorageMock = (function() {
let store = {};
return {
getItem: (key) => store[key] || null,
setItem: (key, value) => { store[key] = value.toString(); },
clear: () => { store = {}; },
removeItem: (key) => { delete store[key]; },
};
})();
global.localStorage = localStorageMock;
});
it('should save and load data from localStorage', () => {
const wrapper = mount(<MyComponent />);
// Проверяем, что при первом рендере компонента данные не загружены
expect(wrapper.find('.data').text()).toBe('');
// Симулируем сохранение данных в localStorage
global.localStorage.setItem('data', 'test data');
wrapper.update();
// Проверяем, что компонент правильно отобразил данные из localStorage
expect(wrapper.find('.data').text()).toBe('test data');
});
});
В этом примере компонент MyComponent использует
localStorage для сохранения и получения данных. Мы мокируем
localStorage, чтобы имитировать работу с ним в тестах, и
проверяем, правильно ли компонент загружает и отображает данные.
jest-localstorage-mockДля удобства можно использовать готовую библиотеку
jest-localstorage-mock, которая автоматически мокирует
localStorage и sessionStorage. Это избавляет
от необходимости вручную создавать мок-объекты и обеспечивает удобную
настройку для тестов.
Пример использования:
npm install --save-dev jest-localstorage-mock
setupTests.js):import 'jest-localstorage-mock';
Теперь в каждом тесте можно использовать localStorage
как обычно, и библиотека будет автоматически мокировать его
поведение.
sessionStorageАналогично localStorage, можно мокировать и
sessionStorage. Основные отличия заключаются только в
продолжительности хранения данных: данные в sessionStorage
исчезают при закрытии вкладки браузера. Мокирование
sessionStorage можно реализовать по аналогии с мокированием
localStorage.
Пример мокирования sessionStorage:
beforeEach(() => {
const sessionStorageMock = (function() {
let store = {};
return {
getItem: (key) => store[key] || null,
setItem: (key, value) => { store[key] = value.toString(); },
clear: () => { store = {}; },
removeItem: (key) => { delete store[key]; },
};
})();
global.sessionStorage = sessionStorageMock;
});
Если компонент использует асинхронные операции с локальным
хранилищем, такие как setItem и getItem, важно
учитывать асинхронность этих операций при написании тестов. Например,
если данные загружаются из localStorage после рендера
компонента, необходимо удостовериться, что тесты ожидают выполнения всех
асинхронных операций перед проверкой результатов.
Пример с асинхронной загрузкой данных:
import React, { useEffect, useState } from 'react';
const MyComponent = () => {
const [data, setData] = useState('');
useEffect(() => {
const fetchData = async () => {
const storedData = await localStorage.getItem('data');
setData(storedData);
};
fetchData();
}, []);
return <div className="data">{data}</div>;
};
export default MyComponent;
Тест для такого компонента:
it('should load data asynchronously from localStorage', async () => {
global.localStorage.setItem('data', 'async data');
const wrapper = mount(<MyComponent />);
// Ждем, пока компонент обновится после загрузки данных
await new Promise((resolve) => setImmediate(resolve));
wrapper.update();
// Проверяем, что данные из localStorage были корректно загружены
expect(wrapper.find('.data').text()).toBe('async data');
});
Мокирование локального хранилища с использованием Jest и Enzyme
позволяет создавать изолированные тесты для компонентов,
взаимодействующих с localStorage или
sessionStorage. Это подход помогает избежать побочных
эффектов, ускоряет тестирование и позволяет легко проверить работу с
хранилищем в разных состояниях.