В разработке на Polymer часто возникает необходимость тестирования компонентов в изоляции от внешних зависимостей. Для этой цели применяются моки (mocks) и стабы (stubs). Они позволяют контролировать поведение функций, сервисов или API, с которыми взаимодействует компонент, без необходимости задействовать их реальную реализацию.
Моки — это объекты или функции, которые имитируют поведение реального объекта и при этом собирают информацию о том, как они использовались. Моки применяются для проверки того, какие методы были вызваны, с какими параметрами и сколько раз.
Стабы — более простые объекты или функции, заменяющие реальную реализацию с заранее определённым поведением. Они не фиксируют информацию о вызовах и используются для управления потоком выполнения.
Пример различия:
// Стаб
function fetchStub() {
return Promise.resolve({ data: 'test' });
}
// Мок
const fetchMock = sinon.mock();
fetchMock.expects('get').once().returns(Promise.resolve({ data: 'test' }));
Polymer-компоненты часто обращаются к API через отдельные сервисы. Для изоляции тестируемого компонента используется замена реальных методов на стабы.
Пример стабирования метода:
import { fixture, html } from '@open-wc/testing';
import './my-component.js';
suite('MyComponent Stubs', () => {
test('stub fetchData method', async () => {
const el = await fixture(html`<my-component></my-component>`);
const originalFetch = el.fetchData;
el.fetchData = () => Promise.resolve('stubbed data');
const result = await el.fetchData();
console.assert(result === 'stubbed data');
el.fetchData = originalFetch; // восстановление оригинала
});
});
Ключевые моменты использования стабов:
Моки позволяют не только заменять функциональность, но и отслеживать вызовы методов. В Polymer это особенно полезно при тестировании событий и обратных вызовов компонентов.
Пример создания мока с использованием Sinon:
import sinon from 'sinon';
import { fixture, html } from '@open-wc/testing';
import './my-component.js';
suite('MyComponent Mocks', () => {
test('mock method call', async () => {
const el = await fixture(html`<my-component></my-component>`);
const callbackMock = sinon.fake();
el.addEventListener('custom-event', callbackMock);
el.dispatchEvent(new CustomEvent('custom-event', { detail: 'data' }));
console.assert(callbackMock.calledOnce);
console.assert(callbackMock.firstCall.args[0].detail === 'data');
});
});
Особенности использования моков:
Часто в одном тесте удобно комбинировать стабы и моки: стабы для управления поведением зависимостей, моки для проверки взаимодействий.
Пример комбинированного подхода:
import sinon from 'sinon';
import { fixture, html } from '@open-wc/testing';
import './my-component.js';
suite('MyComponent Combined', () => {
test('stub and mock', async () => {
const el = await fixture(html`<my-component></my-component>`);
// Стабирование метода
el.fetchData = () => Promise.resolve('stubbed response');
// Мок для проверки события
const eventMock = sinon.fake();
el.addEventListener('data-fetched', eventMock);
await el.fetchData();
el.dispatchEvent(new CustomEvent('data-fetched', { detail: 'stubbed response' }));
console.assert(eventMock.calledOnce);
console.assert(eventMock.firstCall.args[0].detail === 'stubbed response');
});
});
@open-wc/testing вместе с Sinon, так как они
хорошо интегрируются с веб-компонентами.С помощью правильного использования моков и стабов тесты Polymer-компонентов становятся надёжными, быстрыми и изолированными, что облегчает поддержку сложных интерфейсных приложений.