Unit-тестирование компонентов Vue фокусируется на проверке их поведения изолированно, без зависимости от внешних сервисов или глобального состояния приложения. Библиотека Vue Test Utils (VTU) предоставляет инструменты для рендеринга компонентов, взаимодействия с ними и проверки их состояния.
Mount и shallowMount — два ключевых метода для рендеринга компонентов:
mount создаёт полный экземпляр
компонента, включая все дочерние компоненты. Используется, когда
необходимо проверить полное поведение или взаимодействие с вложенными
компонентами.
shallowMount рендерит компонент, но
заменяет дочерние компоненты на заглушки. Подходит для изолированного
тестирования логики компонента без влияния вложенных
компонентов.
import { mount, shallowMount } from '@vue/test-utils';
import MyComponent from '@/components/MyComponent.vue';
const wrapper = mount(MyComponent);
const shallowWrapper = shallowMount(MyComponent);
Ключевой момент: выбор между mount и
shallowMount зависит от цели теста. Для unit-тестов чаще
используется shallowMount.
VTU предоставляет несколько методов для поиска элементов:
wrapper.find(selector) — возвращает
первый найденный элемент, соответствующий селектору.wrapper.findAll(selector) — возвращает
массив всех совпадений.wrapper.get(selector) — аналог
find, но выбрасывает ошибку, если элемент не найден, что
удобно для строгих проверок.Селекторы могут быть CSS-классами, тегами, атрибутами и даже именами компонентов:
const button = wrapper.find('button');
const inputs = wrapper.findAll('input');
const custom = wrapper.findComponent({ name: 'ChildComponent' });
Симуляция событий и изменение состояния компонента — центральная часть unit-тестирования:
trigger(event) — инициирует событие на
элементе.setValue(value) — устанавливает
значение для input-элементов.setProps(props) — обновляет свойства
компонента.setData(data) — обновляет локальное
состояние компонента.Пример:
const input = wrapper.find('input');
await input.setValue('новое значение');
await wrapper.find('form').trigger('submit');
await wrapper.setProps({ isVisible: true });
await wrapper.setData({ count: 5 });
Важно: большинство операций изменяет реактивное
состояние асинхронно, поэтому await используется для
ожидания обновления DOM.
VTU позволяет проверять как реактивное состояние компонента, так и видимый DOM:
wrapper.text() — возвращает текстовое
содержимое компонента.wrapper.html() — возвращает HTML.wrapper.classes() — массив классов
корневого элемента.wrapper.attributes() — объект
атрибутов элемента.wrapper.vm — доступ к экземпляру Vue и
его реактивным данным, методам и вычисляемым свойствам.Пример проверки:
expect(wrapper.text()).toContain('Привет');
expect(wrapper.classes()).toContain('active');
expect(wrapper.vm.count).toBe(5);
Компоненты часто взаимодействуют с внешним миром через события. VTU позволяет проверять их корректную генерацию:
wrapper.emitted() — возвращает объект
с событиями, которые были вызваны.wrapper.emitted('eventName') — массив
вызовов конкретного события.wrapper.emitted('eventName')[0] —
аргументы первого вызова события.Пример:
await wrapper.find('button').trigger('click');
expect(wrapper.emitted()).toHaveProperty('submit');
expect(wrapper.emitted('submit')[0]).toEqual([{ success: true }]);
Ключевой момент: unit-тест должен проверять, что компонент правильно эмиттит события при изменении состояния или взаимодействии с пользователем.
Для изоляции тестов часто используют моки:
Заглушки компонентов (stubs):
заменяют дочерние компоненты простыми версиями, чтобы избежать
тестирования их логики.
const wrapper = shallowMount(ParentComponent, {
stubs: ['ChildComponent']
});Моки методов (methods): позволяют
заменить методы компонента на функции-заглушки.
const wrapper = mount(MyComponent, {
methods: {
fetchData: jest.fn()
}
});Моки плагинов и глобальных свойств
(global): можно подменить Vue Router, Vuex или
любые глобальные свойства.
const wrapper = mount(MyComponent, {
global: {
mocks: {
$t: (msg) => msg
}
}
});Vue обновляет DOM асинхронно. Для корректного тестирования
асинхронных операций необходимо использовать
await nextTick() или асинхронные
ожидания:
import { nextTick } from 'vue';
await wrapper.setData({ count: 1 });
await nextTick();
expect(wrapper.text()).toContain('1');
Использование await обеспечивает, что все реактивные
вычисления завершены до проверки состояния компонента.
describe объединяют тесты по аспектам поведения: рендеринг,
методы, события.get и
строгие ожидания, чтобы тест падал при любых несоответствиях.describe('MyComponent', () => {
it('рендерит текст', () => {
const wrapper = shallowMount(MyComponent);
expect(wrapper.text()).toContain('Привет');
});
it('вызывает событие submit', async () => {
const wrapper = shallowMount(MyComponent);
await wrapper.find('button').trigger('click');
expect(wrapper.emitted('submit')).toHaveLength(1);
});
});
Vue Test Utils тесно интегрируется с Jest. Используются стандартные matchers:
toBe / toEqual — проверка
значения.toContain — проверка текста или
массива.toHaveLength — проверка количества
элементов.toHaveProperty — проверка наличия
события или свойства.Совмещение VTU и Jest обеспечивает надёжные unit-тесты компонентов с полной поддержкой реактивности, событий и асинхронных изменений DOM.
Эта основа позволяет строить детальные и изолированные unit-тесты для Vue-компонентов, охватывая их рендеринг, реактивное состояние, методы, события и взаимодействие с дочерними компонентами.