В Vue.js состояние приложения определяется как совокупность всех
данных, которые влияют на отображение компонентов и поведение
интерфейса. Управление состоянием может осуществляться локально в
отдельных компонентах через data и реактивные свойства,
либо централизованно с помощью Vuex или Pinia. Тестирование состояния
требует понимания, какие данные являются критичными и как изменения этих
данных отражаются на пользовательском интерфейсе.
Ключевые аспекты состояния:
Юнит-тестирование направлено на проверку корректного функционирования
отдельных компонентов и их реактивных данных. В Vue 3 часто используют
@vue/test-utils и Jest или Vitest.
Пример структуры теста для компонента с состоянием:
import { mount } from '@vue/test-utils'
import Counter from '@/components/Counter.vue'
describe('Counter.vue', () => {
it('увеличивает значение при клике', async () => {
const wrapper = mount(Counter)
expect(wrapper.text()).toContain('0')
const button = wrapper.find('button')
await button.trigger('click')
expect(wrapper.text()).toContain('1')
})
})
Основные принципы:
data() или
computed.trigger.Для приложений с Vuex или Pinia проверка состояния часто включает тестирование мутаций, действий и геттеров.
Пример тестирования мутации Vuex:
import { mutations } from '@/store'
const { increment } = mutations
describe('mutations', () => {
it('увеличивает счетчик', () => {
const state = { count: 0 }
increment(state)
expect(state.count).toBe(1)
})
})
Принципы тестирования:
Пример тестирования действия с асинхронным запросом:
import { actions } from '@/store'
import axios from 'axios'
import { vi } from 'vitest'
vi.mock('axios')
describe('actions', () => {
it('загружает данные и коммитит мутацию', async () => {
const commit = vi.fn()
axios.get.mockResolvedValue({ data: { count: 5 } })
await actions.fetchCount({ commit })
expect(commit).toHaveBeenCalledWith('setCount', 5)
})
})
Интеграционные тесты проверяют взаимодействие нескольких компонентов с общим состоянием. Здесь важна проверка корректного потока данных от компонентов к стору и обратно, а также синхронизации реактивного состояния.
Пример подхода:
import { mount } from '@vue/test-utils'
import ParentComponent from '@/components/ParentComponent.vue'
import { createStore } from 'vuex'
const store = createStore({
state: { count: 0 },
mutations: { increment(state) { state.count++ } }
})
const wrapper = mount(ParentComponent, {
global: { plugins: [store] }
})
// Симуляция события, которое вызывает мутацию
await wrapper.find('button.increment').trigger('click')
// Проверка обновленного состояния и отображения
expect(store.state.count).toBe(1)
expect(wrapper.text()).toContain('1')
Компоненты часто используют computed свойства и
наблюдатели (watch). Для тестирования их поведения важно
проверять:
it('computed fullName обновляется при изменении firstName', async () => {
const wrapper = mount({
data: () => ({ firstName: 'John', lastName: 'Doe' }),
computed: {
fullName() { return `${this.firstName} ${this.lastName}` }
},
template: `<div>{{ fullName }}</div>`
})
expect(wrapper.text()).toBe('John Doe')
wrapper.vm.firstName = 'Jane'
await wrapper.vm.$nextTick()
expect(wrapper.text()).toBe('Jane Doe')
})
Тестирование состояния требует контроля внешних зависимостей. Для этого применяются:
await nextTick() для корректного
отслеживания реактивных изменений.Тестирование состояния во Vue.js является фундаментом надежного и предсказуемого приложения. Оно охватывает как простые реактивные свойства компонентов, так и сложные потоки данных в глобальном хранилище, обеспечивая стабильность пользовательского интерфейса при изменении данных.