Мокирование зависимостей

SkateJS — это библиотека для создания веб-компонентов на основе современных стандартов, таких как Custom Elements и Shadow DOM. При разработке компонентов часто возникает необходимость изолированного тестирования, особенно когда компонент взаимодействует с внешними зависимостями, такими как API, хранилища состояния или сторонние сервисы. Мокирование позволяет заменить реальные зависимости на имитации, контролировать их поведение и проверять реакции компонента.


Зачем необходимо мокирование

Мокирование служит для:

  • Изоляции тестируемого компонента от внешних сервисов.
  • Контроля поведения зависимостей для воспроизводимых тестов.
  • Ускорения тестов за счет исключения реальных сетевых запросов или тяжелых вычислений.
  • Проверки, как компонент реагирует на ошибки или нестандартные ответы зависимостей.

Подходы к мокированию

  1. Мокирование через свойства компонента SkateJS позволяет использовать свойства для передачи зависимостей. Вместо прямого импорта сервиса его можно передавать в компонент через пропсы, а в тестах подставлять моки.

    import { define, props, Component } from 'skatejs';
    
    class UserProfile extends Component {
      static props = {
        userService: props.object
      };
    
      connectedCallback() {
        super.connectedCallback();
        this.userService.fetchUser().then(user => {
          this.render(user);
        });
      }
    
      render(user) {
        this.innerHTML = `<p>${user.name}</p>`;
      }
    }
    
    define('user-profile', UserProfile);

    В тестах:

    const mockUserService = {
      fetchUser: () => Promise.resolve({ name: 'Иван' })
    };
    
    const element = document.createElement('user-profile');
    element.userService = mockUserService;
    document.body.appendChild(element);

    Такой подход упрощает замену сервисов на моки и делает компонент полностью тестируемым.


  1. Мокирование через ES-модули Если зависимость импортируется напрямую, можно использовать инструменты вроде jest.mock или аналогичные возможности в других фреймворках тестирования. Это позволяет заменить конкретный модуль на тестовый вариант без изменения компонента.

    import * as api from './api';
    jest.mock('./api', () => ({
      fetchUser: jest.fn(() => Promise.resolve({ name: 'Мария' }))
    }));
    
    import { UserProfile } from './user-profile';
    
    test('рендерит имя пользователя', async () => {
      const element = document.createElement('user-profile');
      document.body.appendChild(element);
      await new Promise(setImmediate);
      expect(element.innerHTML).toContain('Мария');
    });

  1. Мокирование глобальных объектов и API браузера Иногда компонент зависит от fetch, localStorage, window или других глобальных объектов. Их можно временно заменять в тестах:

    const originalFetch = window.fetch;
    window.fetch = jest.fn(() =>
      Promise.resolve({ json: () => Promise.resolve({ data: 123 }) })
    );
    
    // ...тестирование компонента
    
    window.fetch = originalFetch; // восстановление после теста

    Это полезно для проверки поведения компонента при разных ответах сервера без реальных запросов.


Особенности мокирования в SkateJS

  • Слабая связанность компонентов — SkateJS рекомендует минимизировать прямые зависимости. Использование свойств и событий облегчает мокирование.
  • Shadow DOM — при тестировании компонентов с изолированным DOM необходимо учитывать, что элементы находятся внутри shadowRoot. Для проверки содержимого используют element.shadowRoot.querySelector.
  • Асинхронность — многие методы компонентов возвращают промисы. Моки должны корректно имитировать асинхронное поведение, чтобы тесты оставались правдоподобными.

Практическое применение

  • Мокирование API-сервисов позволяет тестировать компонент без необходимости поднятия сервера.
  • Мокирование состояния (например, глобального хранилища или Redux-подобного стейта) дает возможность проверять реакцию компонента на изменение данных.
  • Мокирование утилит (например, библиотек для форматирования дат или чисел) помогает обеспечить предсказуемый вывод без влияния внешних библиотек.

Рекомендации

  • Всегда восстанавливать моки после теста, чтобы не влиять на другие тесты.
  • Использовать отдельные моки для разных сценариев: успешный ответ, ошибка, пустой результат.
  • Отдавать предпочтение мокированию через свойства компонента — это делает компонент гибким и повторно используемым.
  • Асинхронные мок-методы должны возвращать промисы для корректного взаимодействия с компонентом.

Мокирование зависимостей является ключевым инструментом при тестировании SkateJS-компонентов, позволяя создавать изолированные, надежные и воспроизводимые тесты без сложной инфраструктуры.