При тестировании Vue-компонентов часто возникает необходимость изолировать их от внешних зависимостей: сервисов, утилит, библиотек или других компонентов. Для этого используются моки модулей и импортов, что позволяет контролировать поведение зависимостей и проверять реакцию компонента на различные сценарии.
Мокирование заключается в замене реальной реализации модуля на имитацию, которая возвращает предсказуемые значения. Это дает несколько преимуществ:
В Vue Test Utils мокирование тесно связано с возможностями тестового раннера (например, Jest или Vitest), так как именно он предоставляет инструменты для подмены импортов.
Jest предоставляет функцию jest.mock(), позволяющую
заменить любой импортируемый модуль:
import { mount } from '@vue/test-utils';
import UserService from '@/services/UserService';
import UserProfile from '@/components/UserProfile.vue';
jest.mock('@/services/UserService', () => ({
fetchUser: jest.fn(() => Promise.resolve({ id: 1, name: 'Иван' })),
}));
test('должен отображать имя пользователя', async () => {
const wrapper = mount(UserProfile);
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain('Иван');
});
Здесь fetchUser заменен на мок-функцию, которая всегда
возвращает один и тот же объект. Это позволяет тестировать компонент без
обращения к реальному сервису.
Vitest использует схожий синтаксис с Jest, но с небольшой особенностью для модулей ES:
import { vi } from 'vitest';
import { mount } from '@vue/test-utils';
import UserService from '@/services/UserService';
import UserProfile from '@/components/UserProfile.vue';
vi.mock('@/services/UserService', () => ({
fetchUser: vi.fn(() => Promise.resolve({ id: 1, name: 'Мария' })),
}));
test('отображает имя пользователя', async () => {
const wrapper = mount(UserProfile);
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain('Мария');
});
При использовании Vitest важно помнить, что мок должен быть объявлен до импорта тестируемого компонента, иначе реальный модуль уже будет подгружен.
Иногда необходимо заменить не весь модуль, а только отдельные
функции. В Jest это делается через jest.spyOn:
import * as utils from '@/utils/formatDate';
import { mount } from '@vue/test-utils';
import DateDisplay from '@/components/DateDisplay.vue';
jest.spyOn(utils, 'formatDate').mockReturnValue('01.01.2026');
test('отображает отформатированную дату', () => {
const wrapper = mount(DateDisplay, {
props: { date: '2026-01-01T00:00:00Z' },
});
expect(wrapper.text()).toContain('01.01.2026');
});
spyOn позволяет временно переопределять функцию без
изменения остального модуля и легко сбрасывается после теста.
Для сложных проектов часто используют автоматическое мокирование
модулей. В Jest это достигается вызовом
jest.mock('moduleName') без второго аргумента. В этом
случае Jest создает мок-объект с функциями-заглушками.
jest.mock('@/services/UserService');
import UserService from '@/services/UserService';
UserService.fetchUser.mockResolvedValue({ id: 2, name: 'Алексей' });
Автомоки удобны для контроля всех функций модуля и для тестирования ошибок без необходимости писать собственные реализации.
jest.resetAllMocks() или
vi.clearAllMocks().jest.mock('@/services/UserService', () => ({
fetchUser: jest.fn(() => Promise.reject(new Error('Сервис недоступен'))),
}));
Компонент при этом можно проверять на правильное отображение сообщений об ошибках.
Помимо сервисов, Vue Test Utils позволяет мокировать дочерние компоненты:
import { mount } from '@vue/test-utils';
import ParentComponent from '@/components/ParentComponent.vue';
const wrapper = mount(ParentComponent, {
global: {
stubs: {
ChildComponent: {
template: '<div class="mock-child">Мок компонент</div>',
},
},
},
});
expect(wrapper.html()).toContain('Мок компонент');
Такой подход снижает зависимость теста от реализации дочерних компонентов и ускоряет выполнение.
На практике часто требуется одновременно мокировать сервисы и компоненты:
import { mount } from '@vue/test-utils';
import { vi } from 'vitest';
import Parent from '@/components/Parent.vue';
import ApiService from '@/services/ApiService';
vi.mock('@/services/ApiService', () => ({
fetchData: vi.fn(() => Promise.resolve(['item1', 'item2'])),
}));
const wrapper = mount(Parent, {
global: {
stubs: {
Child: true,
},
},
});
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain('item1');
Такой подход делает тесты более предсказуемыми и управляемыми.
Моки модулей и импортов — ключевой инструмент для
изолированного тестирования Vue-компонентов. Они
позволяют полностью контролировать внешние зависимости, симулировать
различные сценарии, ошибки и исключения, а также ускорять тестирование
за счет исключения сетевых запросов и тяжелых вычислений. Использование
jest.mock, vi.mock и jest.spyOn
обеспечивает гибкость при замене функций или целых модулей, а глобальные
стабы компонентов делают тесты компактными и устойчивыми.