Мокирование зависимостей является ключевым инструментом при тестировании приложений на Vue.js. Оно позволяет изолировать компонент или сервис от внешних зависимостей, таких как API-запросы, сторонние библиотеки или глобальные состояния, что обеспечивает более точное и управляемое тестирование.
В Vue.js компоненты часто зависят от сервисов, Vuex store, router и внешних API. Мокирование этих зависимостей позволяет тестировать компоненты как юнит-тесты, избегая непредсказуемого поведения из-за внешних факторов.
Пример структуры компонента с зависимостью:
<template>
<div>
<p>{{ message }}</p>
<button @click="fetchData">Загрузить данные</button>
</div>
</template>
<script>
import apiService from '@/services/apiService';
export default {
data() {
return {
message: ''
};
},
methods: {
async fetchData() {
const result = await apiService.getData();
this.message = result.message;
}
}
};
</script>
В этом примере apiService является внешней зависимостью,
которую можно замокировать для тестирования метода
fetchData.
Jest предоставляет встроенные инструменты для создания моков.
Основные методы: jest.mock() и jest.fn().
Пример мокирования сервиса:
import { shallowMount } from '@vue/test-utils';
import MyComponent from '@/components/MyComponent.vue';
import apiService from '@/services/apiService';
jest.mock('@/services/apiService', () => ({
getData: jest.fn()
}));
describe('MyComponent', () => {
it('должен обновлять message после fetchData', async () => {
apiService.getData.mockResolvedValue({ message: 'Привет, Vue!' });
const wrapper = shallowMount(MyComponent);
await wrapper.vm.fetchData();
expect(wrapper.vm.message).toBe('Привет, Vue!');
});
});
Ключевые моменты:
jest.mock() заменяет весь модуль на объект с
моками.mockResolvedValue() позволяет задать возвращаемое
значение для промиса.Компоненты часто используют mapState,
mapActions или напрямую обращаются к store. Для
тестирования таких компонентов создаётся локальный
store или моки для отдельных действий.
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import Counter from '@/components/Counter.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('Counter', () => {
let actions;
let store;
beforeEach(() => {
actions = {
increment: jest.fn()
};
store = new Vuex.Store({
state: { count: 0 },
actions
});
});
it('вызывает действие increment', () => {
const wrapper = shallowMount(Counter, { store, localVue });
wrapper.find('button').trigger('click');
expect(actions.increment).toHaveBeenCalled();
});
});
Особенности мокирования Vuex:
createLocalVue() предотвращает изменения
глобального Vue.actions) позволяют проверять вызовы без
выполнения реальной логики.state) для проверки
реактивности.Vue Router также часто является зависимостью. Для тестов создаются локальные экземпляры маршрутизатора с необходимыми маршрутами.
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueRouter from 'vue-router';
import MyPage from '@/components/MyPage.vue';
const localVue = createLocalVue();
localVue.use(VueRouter);
const routes = [{ path: '/home', name: 'home' }];
const router = new VueRouter({ routes });
describe('MyPage', () => {
it('редиректит на home', async () => {
const wrapper = shallowMount(MyPage, { localVue, router });
await wrapper.vm.$router.push('/home');
expect(wrapper.vm.$route.name).toBe('home');
});
});
Преимущества мокирования роутера:
В проектах на Vue.js часто используются библиотеки для HTTP-запросов (Axios), уведомлений (Toast), графиков (Chart.js). Их также можно мокировать:
import axios from 'axios';
jest.mock('axios');
axios.get.mockResolvedValue({ data: { id: 1, name: 'Vue' } });
Особенности:
jest.fn() можно использовать для проверки вызовов
функций и аргументов.jest.clearAllMocks() или
jest.resetAllMocks().shallowMount вместо mount, чтобы изолировать
компонент от дочерних компонентов.Мокирование зависимостей в Vue.js обеспечивает предсказуемость и стабильность тестов, снижает время их выполнения и позволяет фокусироваться на логике компонентов без внешних отвлекающих факторов.