Лучшие практики

Для начала работы с Vue Test Utils требуется установить библиотеку через npm или yarn:

npm install @vue/test-utils --save-dev

или

yarn add @vue/test-utils --dev

Важно использовать совместимую версию с текущей версией Vue. Для Vue 3 необходима версия @vue/test-utils@next. Настройка тестового окружения обычно включает Jest или Vitest, а также конфигурацию сборщика (Vite или Webpack), чтобы корректно обрабатывать .vue файлы.

Монтирование компонентов

Базовый метод работы с компонентами — функция mount. Она создаёт экземпляр компонента и позволяет тестировать его в изолированном окружении:

import { mount } from '@vue/test-utils';
import MyComponent from '@/components/MyComponent.vue';

const wrapper = mount(MyComponent, {
  props: { title: 'Тест' },
});

Ключевые моменты:

  • mount рендерит компонент полностью, включая дочерние.
  • shallowMount используется для изоляции: дочерние компоненты заменяются заглушками. Это снижает сложность и ускоряет тесты.

Работа с пропсами и состоянием

Пропсы можно передавать напрямую через опцию props при монтировании:

const wrapper = mount(MyComponent, {
  props: { active: true }
});

Для динамического изменения пропсов используется метод setProps:

await wrapper.setProps({ active: false });
expect(wrapper.props('active')).toBe(false);

Состояние компонента (data) можно тестировать через vm:

expect(wrapper.vm.count).toBe(0);
wrapper.vm.increment();
expect(wrapper.vm.count).toBe(1);

Взаимодействие с DOM

Vue Test Utils предоставляет мощные методы для работы с DOM:

  • find — поиск одного элемента по селектору.
  • findAll — поиск множества элементов.
  • text() — получение текстового содержимого.
  • html() — получение HTML-кода элемента.

Пример:

const button = wrapper.find('button');
await button.trigger('click');
expect(wrapper.text()).toContain('Нажато');

Важно: все асинхронные действия, включая события и обновление состояния, должны ожидать с await wrapper.vm.$nextTick() или с использованием await при вызове методов, возвращающих промис.

Тестирование событий

События компонента можно проверять через:

await wrapper.find('button').trigger('click');
expect(wrapper.emitted('submit')).toHaveLength(1);

Ключевые моменты:

  • emitted() возвращает объект с массивами всех сгенерированных событий.
  • Можно проверять параметры события: expect(wrapper.emitted('submit')[0]).toEqual([{ name: 'Тест' }]).

Работа с слотами

Vue Test Utils поддерживает тестирование слотов. Слоты передаются через опцию slots:

const wrapper = mount(MyComponent, {
  slots: { default: '<span>Слот</span>' }
});
expect(wrapper.html()).toContain('Слот');

Можно тестировать как named slots, так и default slot. Это позволяет полностью контролировать содержимое, рендеримое внутри компонента.

Моки и заглушки

Для сложных компонентов, которые зависят от глобальных провайдеров или дочерних компонентов, рекомендуется использовать mocks и stubs:

const wrapper = mount(MyComponent, {
  global: {
    mocks: { $router: { push: jest.fn() } },
    stubs: { ChildComponent: true }
  }
});
  • mocks — позволяет подменять глобальные свойства ($store, $router).
  • stubs — заменяет компоненты на простые заглушки, ускоряя тесты и снижая зависимость от реализации дочерних компонентов.

Асинхронное тестирование

Для компонентов с асинхронными эффектами (axios, setTimeout, nextTick) необходимо использовать async/await:

await wrapper.vm.loadData();
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain('Данные загружены');

Рекомендация: использовать мокированные функции для HTTP-запросов, чтобы тесты были детерминированными и быстрыми.

Лучшие практики написания тестов

  1. Тестировать поведение, а не реализацию. Проверять внешний результат, а не внутренние методы.
  2. Использовать shallowMount для изоляции, если тест проверяет только конкретный компонент.
  3. Делать тесты детерминированными. Моки и заглушки должны полностью контролировать сторонние зависимости.
  4. Явно ожидать асинхронные обновления. Пропуски await могут приводить к нестабильным тестам.
  5. Минимизировать дублирование кода через фабрики монтирования компонентов с дефолтными пропсами и слотами.
  6. Тестировать события и слоты — это ключевой элемент взаимодействия компонентов.

Интеграция с Jest и Vitest

Vue Test Utils идеально интегрируется с Jest или Vitest:

  • Поддержка снапшотов: expect(wrapper.html()).toMatchSnapshot().
  • Проверка вызовов моков: expect(mockFn).toHaveBeenCalledWith(arg).
  • Асинхронные тесты через async/await без дополнительной конфигурации.

Эта комбинация позволяет создавать масштабируемую систему тестов, охватывающую как юнит-тестирование компонентов, так и их взаимодействие в составе приложения.