Понятие стаба и мока

В контексте тестирования компонентов Vue.js, особенно с использованием Vue Test Utils, ключевыми инструментами для изоляции поведения являются стабы и моки. Их правильное применение позволяет тестировать компоненты независимо от внешних зависимостей, таких как API, Vuex или дочерние компоненты.


Стабы

Стаб (stub) представляет собой заглушку для компонента, функции или метода, который не является предметом текущего теста. Основная цель стаба — заменить сложный или сторонний функционал на упрощённый вариант, который позволяет сосредоточиться на тестируемом компоненте.

Применение в Vue Test Utils:

  1. Заглушка дочерних компонентов
import { shallowMount } from '@vue/test-utils';
import ParentComponent from '@/components/ParentComponent.vue';
import ChildComponent from '@/components/ChildComponent.vue';

const wrapper = shallowMount(ParentComponent, {
  stubs: {
    ChildComponent: true
  }
});
  • Использование true создаёт минимальную заглушку без содержимого.
  • Можно передать кастомный шаблон:
stubs: {
  ChildComponent: '<div class="stub"></div>'
}
  1. Заглушка глобальных компонентов
const wrapper = shallowMount(ParentComponent, {
  global: {
    stubs: ['RouterLink', 'FontAwesomeIcon']
  }
});

Это позволяет избежать необходимости загружать весь роутер или сторонние библиотеки при юнит-тестировании.

Преимущества стаба:

  • Сокращение времени выполнения тестов.
  • Изоляция тестируемого компонента.
  • Предсказуемость поведения дочерних компонентов.

Ограничения:

  • Стабы не выполняют реальную логику компонентов.
  • При чрезмерном использовании можно пропустить ошибки взаимодействия компонентов.

Моки

Мок (mock) — это объект или функция, имитирующая поведение зависимости, но с возможностью отслеживания вызовов, аргументов и результатов. Основное отличие от стаба в том, что мок не просто заглушка, а инструмент для верификации взаимодействия.

Применение в Vue Test Utils:

  1. Моки методов и функций
import { mount } from '@vue/test-utils';
import MyComponent from '@/components/MyComponent.vue';

const myMethodMock = jest.fn();

const wrapper = mount(MyComponent, {
  methods: {
    fetchData: myMethodMock
  }
});

wrapper.vm.fetchData();

expect(myMethodMock).toHaveBeenCalled();
  • Позволяет проверить, что метод был вызван с правильными параметрами.
  • Используется для контроля побочных эффектов без их реального выполнения.
  1. Моки глобальных объектов
const $axiosMock = {
  get: jest.fn(() => Promise.resolve({ data: { id: 1 } }))
};

const wrapper = mount(MyComponent, {
  global: {
    mocks: {
      $axios: $axiosMock
    }
  }
});
  • Позволяет изолировать компонент от внешнего API.
  • Можно проверять вызовы $axios.get и параметры запроса.
  1. Моки Vuex
import { createStore } from 'vuex';

const actionsMock = {
  fetchItems: jest.fn()
};

const store = createStore({
  actions: actionsMock
});

const wrapper = mount(MyComponent, {
  global: {
    plugins: [store]
  }
});

wrapper.vm.$store.dispatch('fetchItems');
expect(actionsMock.fetchItems).toHaveBeenCalled();

Моки помогают убедиться, что компонент корректно взаимодействует с глобальными зависимостями.


Отличия стаба от мока

Параметр Стаб Мок
Основная цель Замена компонента/функции без логики Имитация функциональности с отслеживанием вызовов
Контроль вызовов Нет Да
Используется для Упрощения тестовой среды Верификации взаимодействия с зависимостями
Примеры stubs: { ChildComponent: true } jest.fn() для методов или Vuex actions

Практические рекомендации

  1. Комбинированное использование: часто стабы и моки применяются вместе. Дочерний компонент можно заглушить, а его события мокировать для проверки реакции родителя.
  2. Минимализм: замещать только те зависимости, которые мешают тестированию.
  3. Явное именование: стабы и моки должны быть легко различимы по названиям (ChildStub, axiosMock).
  4. Асинхронные мок-функции: при тестировании API использовать промисы для точной имитации сетевых вызовов.

Структурированное применение стаба и мока позволяет писать модульные, предсказуемые и изолированные тесты, которые гарантируют корректность работы Vue-компонентов без необходимости подключения всей инфраструктуры приложения.