Для начала работы с Vue Test Utils требуется установка библиотеки через npm или yarn:
npm install @vue/test-utils --save-dev
# или
yarn add @vue/test-utils --dev
Vue Test Utils (VTU) позволяет создавать шаблоны компонентов
и взаимодействовать с ними в изолированной среде. Основная точка входа —
функция mount, которая рендерит компонент в тестовой
среде.
import { mount } from '@vue/test-utils';
import MyComponent from '@/components/MyComponent.vue';
const wrapper = mount(MyComponent, {
props: { title: 'Тестовый заголовок' }
});
wrapper — это объект, предоставляющий методы для поиска
элементов, проверки их состояния и симуляции пользовательских
действий.
Тесты с использованием VTU обычно строятся вокруг трёх ключевых элементов:
wrapper) — рендеринг
компонента.Пример простого теста:
test('отображает переданный заголовок', () => {
const wrapper = mount(MyComponent, { props: { title: 'Привет' } });
expect(wrapper.text()).toContain('Привет');
});
VTU предоставляет методы для поиска элементов:
wrapper.find(selector) — возвращает первый элемент,
соответствующий селектору.wrapper.findAll(selector) — возвращает массив всех
элементов по селектору.Для проверки содержимого и атрибутов используется:
const button = wrapper.find('button');
expect(button.text()).toBe('Нажми меня');
expect(button.attributes('disabled')).toBeUndefined();
Методы classes(), attributes(),
element и html() позволяют получать состояние
элемента и проверять соответствие ожиданиям.
Vue Test Utils позволяет симулировать события через метод
trigger:
const button = wrapper.find('button');
await button.trigger('click');
expect(wrapper.emitted()).toHaveProperty('submit');
Можно передавать объект события для имитации реальных условий:
await button.trigger('keydown.enter', { key: 'Enter' });
Пропсы можно передавать при создании wrapper или
динамически изменять через setProps:
await wrapper.setProps({ title: 'Новый заголовок' });
expect(wrapper.text()).toContain('Новый заголовок');
Реактивные данные проверяются через изменение состояния компонента:
wrapper.vm.counter = 5;
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain('5');
nextTick необходим для обновления DOM после изменения
реактивных данных.
Компоненты часто взаимодействуют через $emit. Проверка
событий выполняется через методы emitted и
emittedByOrder:
await wrapper.find('button').trigger('click');
expect(wrapper.emitted('submit')).toHaveLength(1);
expect(wrapper.emitted('submit')[0]).toEqual([{ id: 1 }]);
Можно проверять порядок вызовов событий и их аргументы, что важно при сложных пользовательских сценариях.
VTU позволяет тестировать компоненты в изоляции или вместе с дочерними:
import { shallowMount } from '@vue/test-utils';
const wrapper = shallowMount(MyComponent);
const wrapper = mount(MyComponent);
shallowMount ускоряет тесты и уменьшает зависимость от
других компонентов.
Компоненты часто выполняют асинхронные действия, например, запросы к API. VTU интегрируется с Jest или Vitest для работы с асинхронным кодом:
await wrapper.vm.loadData();
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain('Данные загружены');
Методы flushPromises или nextTick
обеспечивают корректное завершение всех промисов перед проверкой
результатов.
Для анализа покрытия тестами используется инструмент
jest --coverage или аналогичные для Vitest. Отчёт
содержит:
VTU в сочетании с Jest позволяет выявить участки кода без тестов, а также проверить корректность рендеринга и реактивности.
describe.test или
it.beforeEach для создания нового
wrapper перед каждым тестом, чтобы избежать побочных
эффектов.shallowMount для изоляции тестов и ускорения
их выполнения.describe('MyComponent', () => {
let wrapper;
beforeEach(() => {
wrapper = shallowMount(MyComponent);
});
test('отображает текст по умолчанию', () => {
expect(wrapper.text()).toContain('Заголовок');
});
test('реагирует на изменение пропса', async () => {
await wrapper.setProps({ title: 'Новый заголовок' });
expect(wrapper.text()).toContain('Новый заголовок');
});
});
VTU позволяет подключать Vuex и Vue Router для тестирования компонентов в контексте приложения:
import { createStore } from 'vuex';
import { createRouter, createWebHistory } from 'vue-router';
const store = createStore({ state: { count: 0 } });
const router = createRouter({ history: createWebHistory(), routes: [] });
const wrapper = mount(MyComponent, {
global: {
plugins: [store, router]
}
});
global.plugins и global.mocks позволяют
настраивать глобальные зависимости без необходимости создавать
полноценное приложение.