Тестирование Vuex store — критически важный этап в разработке приложений на Vue.js, поскольку store управляет состоянием и логикой приложения. Vue Test Utils предоставляет инструменты для интеграции с компонентами, однако для unit-тестирования store лучше использовать специализированные подходы, позволяющие изолировать логику.
Vuex store состоит из state, getters, mutations, actions и modules. При тестировании важно разделять эти части, так как каждая требует специфического подхода:
State и mutations являются самым простым для unit-тестирования уровнем. Для этого создается изолированный store:
import { createStore } from 'vuex'
import counter from '@/store/modules/counter'
describe('mutations', () => {
it('increment увеличивает значение state на 1', () => {
const state = { count: 0 }
counter.mutations.increment(state)
expect(state.count).toBe(1)
})
it('decrement уменьшает значение state на 1', () => {
const state = { count: 2 }
counter.mutations.decrement(state)
expect(state.count).toBe(1)
})
})
Ключевой момент: mutations всегда вызываются с state, и их результат проверяется через непосредственное изменение этого state.
Getters — чистые функции, принимающие state и возвращающие вычисленное значение:
describe('getters', () => {
it('doubleCount возвращает удвоенное значение count', () => {
const state = { count: 5 }
const result = counter.getters.doubleCount(state)
expect(result).toBe(10)
})
})
Важно проверять не только корректность вычислений, но и поведение при граничных значениях state.
Actions сложнее из-за асинхронности и зависимости от commit/dispatch. Обычно используют мок-функции для этих методов:
describe('actions', () => {
it('incrementAsync вызывает commit после задержки', async () => {
const commit = jest.fn()
await counter.actions.incrementAsync({ commit })
expect(commit).toHaveBeenCalledWith('increment')
})
})
Если action использует API-запросы, необходимо мокировать внешние вызовы с помощью jest.mock или axios-mock-adapter, чтобы тест оставался изолированным.
Модули Vuex можно тестировать отдельно, создавая store с конкретным модулем:
import { createStore } from 'vuex'
import counter from '@/store/modules/counter'
const store = createStore({
modules: {
counter
}
})
describe('module counter', () => {
it('инициализируется с правильным state', () => {
expect(store.state.counter.count).toBe(0)
})
it('commit mutation через store работает', () => {
store.commit('counter/increment')
expect(store.state.counter.count).toBe(1)
})
})
Обязательное правило: namespace модулей влияет на вызов commit/dispatch, что нужно учитывать при тестировании.
Vue Test Utils позволяет подключать store к компонентам и проверять взаимодействие компонентов с state:
import { mount } from '@vue/test-utils'
import Counter from '@/components/Counter.vue'
import { createStore } from 'vuex'
import counter from '@/store/modules/counter'
const store = createStore({
modules: { counter }
})
describe('Counter.vue', () => {
it('отображает текущее значение count', () => {
const wrapper = mount(Counter, { global: { plugins: [store] } })
expect(wrapper.text()).toContain('0')
})
it('увеличивает count при клике на кнопку', async () => {
const wrapper = mount(Counter, { global: { plugins: [store] } })
await wrapper.find('button.increment').trigger('click')
expect(store.state.counter.count).toBe(1)
})
})
Тестирование через компонент позволяет проверять интеграцию store и UI, однако для unit-тестов предпочтительно тестировать store отдельно.
Такой подход обеспечивает детальное покрытие Vuex store, гарантируя, что изменения состояния и асинхронная логика работают корректно независимо от UI.