Тестирование JavaScript-кода, взаимодействующего с браузерными API,
требует точного контроля среды выполнения. В реальных условиях браузер
предоставляет множество глобальных объектов и функций —
window, document, fetch,
localStorage, sessionStorage,
navigator, alert и др. При запуске тестов
через Karma необходимо изолировать их от реальных браузерных эффектов,
чтобы гарантировать воспроизводимость и независимость результатов. Для
этого используется мокирование (mocking) — замена реальных функций и
объектов их тестовыми аналогами.
В браузере глобальная область видимости представлена объектом
window. Часто требуется мокировать:
window.alert, window.confirm,
window.prompt Эти методы напрямую влияют на
пользовательский интерфейс. Для тестов создаются заглушки, которые
фиксируют вызовы, но не блокируют выполнение кода.beforeEach(() => {
spyOn(window, 'alert'); // Перехватывает вызовы alert
});
it('вызывает alert с правильным сообщением', () => {
someFunctionThatCallsAlert();
expect(window.alert).toHaveBeenCalledWith('Привет');
});
localStorage и
sessionStorage Для тестов создаются
объекты-заглушки, имитирующие методы getItem,
setItem, removeItem, clear.beforeEach(() => {
let store = {};
spyOn(window.localStorage, 'getItem').and.callFake(key => store[key] || null);
spyOn(window.localStorage, 'setItem').and.callFake((key, value) => { store[key] = value; });
spyOn(window.localStorage, 'removeItem').and.callFake(key => { delete store[key]; });
spyOn(window.localStorage, 'clear').and.callFake(() => { store = {}; });
});
Для тестирования функций, использующих fetch или
XMLHttpRequest, создаются поддельные реализации:
fetchbeforeEach(() => {
spyOn(window, 'fetch').and.callFake((url, options) => {
return Promise.resolve({
ok: true,
json: () => Promise.resolve({ data: 'mocked' })
});
});
});
it('обрабатывает ответ fetch', async () => {
const result = await fetchData(); // Внутри fetchData вызывается window.fetch
expect(result.data).toBe('mocked');
});
XMLHttpRequest Karma запускается в
реальном браузере, но для юнит-тестов проще использовать библиотеку
jasmine-ajax:beforeEach(() => {
jasmine.Ajax.install();
});
afterEach(() => {
jasmine.Ajax.uninstall();
});
it('отправляет GET-запрос и получает ответ', () => {
fetchDataViaXHR();
const request = jasmine.Ajax.requests.mostRecent();
expect(request.url).toBe('/api/data');
request.respondWith({
status: 200,
responseText: '{"data":"mocked"}'
});
});
Функции типа setTimeout, setInterval также
часто требуют контроля:
beforeEach(() => {
jasmine.clock().install();
});
afterEach(() => {
jasmine.clock().uninstall();
});
it('вызывает функцию через 1 секунду', () => {
const callback = jasmine.createSpy('callback');
setTimeout(callback, 1000);
jasmine.clock().tick(1000);
expect(callback).toHaveBeenCalled();
});
Использование таймеров с моками обеспечивает синхронное тестирование асинхронного кода, что особенно важно для Karma, где асинхронные процессы могут влиять на порядок выполнения тестов.
Мокирование элементов DOM позволяет тестировать взаимодействие с документом без реального отображения:
beforeEach(() => {
const div = document.createElement('div');
div.id = 'test-container';
document.body.appendChild(div);
});
afterEach(() => {
const div = document.getElementById('test-container');
if (div) document.body.removeChild(div);
});
it('изменяет текст элемента', () => {
const el = document.getElementById('test-container');
el.textContent = 'Hello';
updateElementText(el, 'World');
expect(el.textContent).toBe('World');
});
Использование моков для DOM предотвращает побочные эффекты между тестами и ускоряет выполнение, так как не требуется рендеринг сложных компонентов.
Помимо встроенных возможностей Jasmine, Karma позволяет использовать дополнительные библиотеки:
Применение этих инструментов повышает гибкость тестов и позволяет точно контролировать поведение browser API без обращения к реальному браузеру.
afterEach).spyOn) для проверки вызовов
функций, вместо изменения поведения реальных методов.Контролируемое мокирование browser API делает тесты надёжными, предсказуемыми и полностью изолированными от внешних факторов, обеспечивая стабильность и скорость при работе с Karma.