Мокирование глобальных объектов в Jest представляет собой важный
аспект тестирования, особенно при работе с кодом, который зависит от
глобальных объектов или внешних библиотек. Глобальные объекты, такие как
window, document, console, а
также глобальные функции, такие как setTimeout или
fetch, часто используются в приложениях и могут привести к
непредсказуемым результатам при тестировании. В таких случаях необходимы
специальные методы мокирования, чтобы изолировать тестируемый код от
внешних зависимостей.
Jest предоставляет встроенные функции для мокирования, которые позволяют заменить глобальные объекты на фиктивные, контролируемые версии. Это помогает избежать побочных эффектов при запуске тестов и позволяет тестировать функциональность в изолированной среде.
Для мокирования глобальных объектов обычно используют несколько подходов:
setTimeout, setInterval,
console.log и другие.fetch или API браузера.jest.spyOn — для
создания шпионов на существующие функции.jest.spyOnДля начала рассмотрим, как использовать метод jest.spyOn
для мокирования глобальных объектов. Этот метод позволяет наблюдать за
функциями и изменять их поведение.
test('should mock console.log', () => {
const spy = jest.spyOn(console, 'log').mockImplementation(() => {});
console.log('Hello, world!');
expect(spy).toHaveBeenCalledWith('Hello, world!');
spy.mockRestore();
});
Здесь мы создаём шпиона на console.log, который
перехватывает вызовы этой функции и заменяет её поведение. После теста
шпион восстанавливается с помощью метода mockRestore.
setTimeout или
setIntervalОдним из распространённых случаев является мокирование функций
таймеров — setTimeout и setInterval. В
реальной среде эти функции могут использоваться для задержек или
повторяющихся действий, но для тестирования часто требуется заменить их
на фиктивные реализации, чтобы избежать задержек в процессе выполнения
теста.
Jest предоставляет встроенную поддержку для мокирования таймеров с
помощью функции jest.useFakeTimers().
test('should mock setTimeout', () => {
jest.useFakeTimers();
const callback = jest.fn();
setTimeout(callback, 1000);
jest.advanceTimersByTime(1000); // Пропускаем 1000 мс
expect(callback).toHaveBeenCalled();
});
Здесь используется метод jest.useFakeTimers(), чтобы
Jest мог управлять временем. Функция
jest.advanceTimersByTime() позволяет “перематывать” время
вперёд, что даёт возможность проверять поведение кода, который
использует таймеры.
fetch)Мокирование внешних API, таких как fetch, представляет
собой важный аспект тестирования приложений, которые делают
HTTP-запросы. Вместо того чтобы реально отправлять запросы в сеть, можно
использовать мокированные версии этих API для тестирования.
Для мокирования fetch можно использовать
jest.fn(), чтобы заменить его на фиктивную функцию:
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ data: 'test data' }),
})
);
test('should fetch data from API', async () => {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
expect(data).toEqual({ data: 'test data' });
expect(fetch).toHaveBeenCalledWith('https://api.example.com/data');
});
Здесь мы заменяем глобальный fetch на фиктивную функцию,
которая возвращает заранее подготовленный результат. Это позволяет
тестировать код, который зависит от сети, без выполнения реальных
HTTP-запросов.
Некоторые тестируемые приложения могут сильно зависеть от объектов
браузера, таких как window, document,
localStorage и других. Для мокирования таких объектов Jest
также предоставляет специальные методы.
Для мокирования объектов браузера, таких как window или
document, можно использовать
Object.defineProperty() или напрямую заменять глобальные
объекты на моки:
test('should mock window.innerWidth', () => {
const originalWidth = window.innerWidth;
Object.defineProperty(window, 'innerWidth', { value: 1024 });
expect(window.innerWidth).toBe(1024);
// Восстановление оригинального значения
Object.defineProperty(window, 'innerWidth', { value: originalWidth });
});
Этот подход позволяет легко заменить свойства глобальных объектов на значения, подходящие для тестирования. Важно помнить, что при использовании таких методов необходимо восстанавливать оригинальные значения после выполнения теста, чтобы избежать влияния на другие тесты.
Если код зависит от событий, таких как click,
resize или другие, можно использовать мокирование
событийных обработчиков. Вместо того чтобы генерировать реальные
события, можно использовать jest.fn() для создания моков
обработчиков.
test('should handle click event', () => {
const handleClick = jest.fn();
const button = document.createElement('button');
button.addEventListener('click', handleClick);
button.click();
expect(handleClick).toHaveBeenCalled();
});
Здесь создаётся элемент кнопки, на который навешивается мокированная функция обработчика события. Когда кнопка кликается, проверяется, был ли вызван обработчик.
fetch,
важно, чтобы возвращаемое значение соответствовало структуре ответа от
настоящего API.Jest предоставляет гибкие инструменты для мокирования глобальных объектов, что позволяет тестировать код в условиях, приближённых к реальной работе, без зависимости от внешних факторов.