Мокирование хуков

Haunted — это библиотека для создания веб-компонентов на основе функционального подхода и хуков, вдохновлённая React. Одной из важных задач при разработке сложных компонентов является тестирование. В этом контексте мокирование хуков становится необходимым инструментом для изоляции компонентов и контроля их поведения.


Основные принципы мокирования

Мокирование хуков в Haunted опирается на несколько ключевых моментов:

  1. Изоляция логики компонента Хуки инкапсулируют состояние и побочные эффекты. Для корректного тестирования важно заменить реальную реализацию хуков на заглушки (mocks), которые возвращают предсказуемые значения.

  2. Контроль состояния Моки позволяют задавать начальное состояние и отслеживать изменения без реального рендеринга сложных структур или сетевых запросов.

  3. Предсказуемость побочных эффектов Вместо выполнения useEffect, который может инициировать сетевые запросы или анимации, мок возвращает заранее определённое поведение.


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

  1. Замена импорта хуков Если хук находится в отдельном модуле, его можно подменить с помощью средств тестирования, например, Jest:
import { useCounter } from './hooks';
jest.mock('./hooks');

useCounter.mockImplementation(() => {
  return [42, () => {}]; // фиксированное значение состояния и пустая функция обновления
});

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

  1. Патчинг хуков внутри компонента Иногда хуки определены непосредственно внутри файла компонента. В этом случае можно экспортировать их отдельно для тестов:
export const useToggle = () => {
  const [value, setValue] = useState(false);
  const toggle = () => setValue(!value);
  return [value, toggle];
};

// В тесте
import * as hooks from './component';
jest.spyOn(hooks, 'useToggle').mockReturnValue([true, () => {}]);

Такой способ сохраняет доступ к исходному компоненту, но позволяет контролировать поведение состояния.


Мокирование встроенных хуков

Haunted предоставляет базовые хуки: useState, useEffect, useRef, useReducer и другие. Для тестирования компонентов часто необходимо мокировать их стандартное поведение.

  • useState Возвращает фиксированное состояние и заглушку функции обновления:
jest.spyOn(Haunted, 'useState').mockImplementation((initial) => [initial, () => {}]);
  • useEffect Для предотвращения выполнения побочных эффектов можно заменить на noop:
jest.spyOn(Haunted, 'useEffect').mockImplementation(() => {});
  • useReducer Позволяет контролировать действия и состояние редьюсера:
jest.spyOn(Haunted, 'useReducer').mockImplementation((reducer, initial) => [initial, jest.fn()]);

Практика использования в тестах

  1. Тестирование рендеринга Моки состояния позволяют проверять, что компонент корректно отображает данные без реального изменения состояния:
import { html, render } from 'lit';
import { MyComponent } from './my-component';
import * as hooks from './hooks';

jest.spyOn(hooks, 'useCounter').mockReturnValue([10, () => {}]);

const container = document.createElement('div');
render(html`<${MyComponent}></${MyComponent}>`, container);
expect(container.textContent).toContain('10');
  1. Тестирование событий Мокированные функции обновления состояния позволяют имитировать взаимодействие пользователя:
const mockSet = jest.fn();
jest.spyOn(hooks, 'useCounter').mockReturnValue([0, mockSet]);

// эмулируем клик
container.querySelector('button').click();
expect(mockSet).toHaveBeenCalled();
  1. Комбинация с асинхронными эффектами Если компонент использует useEffect для загрузки данных, можно мокировать fetch или API и одновременно отключить эффект:
jest.spyOn(Haunted, 'useEffect').mockImplementation((fn) => fn());
global.fetch = jest.fn().mockResolvedValue({ json: () => ({ id: 1 }) });

Советы по организации моков

  • Все хуки, подлежащие мокированию, лучше выносить в отдельные модули, чтобы облегчить их подмену.
  • Для сложных компонентов удобно создавать фабрики моков, возвращающие разные состояния для разных сценариев тестирования.
  • После тестов рекомендуется очищать моки с помощью jest.resetAllMocks() для предотвращения нежелательных побочных эффектов между тестами.

Заключение по технике

Мокирование хуков в Haunted позволяет тестировать компоненты независимо от их внутренней логики, контролировать состояние и побочные эффекты, а также создавать предсказуемую среду для юнит-тестирования. Грамотно организованные моки повышают надёжность тестов и ускоряют процесс разработки сложных веб-компонентов.