Тестирование computed из store

В экосистеме Vue.js computed свойства играют ключевую роль в реактивном отображении состояния, часто зависящего от Vuex store. Правильное тестирование этих вычисляемых свойств позволяет убедиться, что компоненты корректно реагируют на изменения состояния приложения.

Подготовка окружения для тестирования

Для работы с Vue Test Utils потребуется:

  • Vue Test Utils — библиотека для изолированного рендеринга компонентов.
  • Jest (или другой тестовый раннер) — для организации тестов.
  • Vuex — для создания store, который используется компонентом.

Пример установки зависимостей через npm:

npm install @vue/test-utils vuex jest --save-dev

Монтирование компонента с store

Для тестирования computed свойств, зависящих от store, необходимо передавать mock store или реальный экземпляр Vuex. Это достигается через параметр global.plugins при монтировании компонента:

import { mount } from '@vue/test-utils';
import Vuex from 'vuex';
import MyComponent from '@/components/MyComponent.vue';

const state = {
  count: 5
};

const getters = {
  doubleCount: (state) => state.count * 2
};

const store = new Vuex.Store({
  state,
  getters
});

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

Здесь ключевым моментом является использование getters для вычисляемых значений. Компонент может иметь computed свойство, которое напрямую использует mapGetters или обращается к store через this.$store.getters.

Тестирование computed свойства

После монтирования компонента проверка computed свойства выполняется через обращение к экземпляру компонента wrapper.vm:

test('computed doubleCount возвращает правильное значение', () => {
  expect(wrapper.vm.doubleCount).toBe(10);
});

Особенности:

  • wrapper.vm содержит экземпляр Vue-компонента.
  • Любые computed свойства, зависящие от state или getters, доступны напрямую.
  • Проверка значения выполняется без рендеринга DOM, что ускоряет тестирование.

Тестирование реакции на изменение состояния store

Одним из основных преимуществ Vuex является реактивность. Чтобы проверить, что computed свойство корректно обновляется при изменении состояния:

test('computed обновляется при изменении state', async () => {
  store.state.count = 10;
  await wrapper.vm.$nextTick();
  expect(wrapper.vm.doubleCount).toBe(20);
});

Ключевые моменты:

  • Изменение state напрямую через store имитирует действия приложения.
  • Использование await wrapper.vm.$nextTick() гарантирует, что Vue успел пересчитать computed.
  • Такой подход позволяет тестировать сложные зависимости между store и компонентом.

Использование mock store для изоляции

Для unit-тестов предпочтительно использовать mock store вместо реального Vuex. Это позволяет полностью контролировать состояние и поведение getters:

const mockGetters = {
  doubleCount: () => 42
};

const wrapper = mount(MyComponent, {
  global: {
    mocks: {
      $store: {
        getters: mockGetters
      }
    }
  }
});

test('computed возвращает значение из mock getters', () => {
  expect(wrapper.vm.doubleCount).toBe(42);
});

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

  • Изоляция теста от реального Vuex.
  • Возможность точно задавать поведение getters.
  • Упрощение тестов для компонентов с большим количеством зависимостей.

Тестирование computed с mapState и mapGetters

Vue предоставляет вспомогательные функции для подключения к store: mapState и mapGetters. При их использовании тестирование не изменяется, но важно учитывать правильное определение store при монтировании компонента:

computed: {
  ...mapGetters(['doubleCount'])
}

В тесте:

expect(wrapper.vm.doubleCount).toBe(store.getters.doubleCount);

Если используется mapState:

computed: {
  ...mapState(['count'])
}

Тогда проверка computed свойства напрямую связана с state:

expect(wrapper.vm.count).toBe(store.state.count);

Проверка вычисляемых свойств с асинхронными действиями

Иногда computed свойства зависят от результатов асинхронных операций через store. В этом случае рекомендуется использовать мокнутые actions и имитацию обновления state:

const actions = {
  fetchCount: jest.fn(() => {
    store.state.count = 15;
  })
};

await actions.fetchCount();
await wrapper.vm.$nextTick();
expect(wrapper.vm.doubleCount).toBe(30);

Такой подход позволяет тестировать логику computed, не выполняя реальных HTTP-запросов.

Итоговые рекомендации по тестированию computed

  • Всегда монтировать компонент с store (реальным или mock).
  • Проверять начальные значения computed.
  • Тестировать реакцию на изменение состояния.
  • Использовать await wrapper.vm.$nextTick() для обновления реактивных данных.
  • Для изоляции использовать mock store и mock getters.

Этот подход позволяет покрывать unit-тестами все вычисляемые свойства компонента, полностью контролируя зависимость от Vuex store.