Тестирование компонентов Vue часто сталкивается с проблемами производительности и предсказуемости поведения при множественных вызовах одних и тех же функций или рендеринге одинаковых компонентов. Кэширование в тестах позволяет оптимизировать выполнение, избежать повторного создания экземпляров компонентов и сократить количество лишних асинхронных операций.
Кэширование в контексте тестирования Vue-компонентов заключается в сохранении результатов выполнения определённых операций для последующего повторного использования. Основные сценарии применения:
wrapper.find, wrapper.findAll)
можно закэшировать для многократного использования.Для компонентов, рендер которых является дорогой операцией,
применяется хранение wrapper в локальной области видимости
тестового файла:
import { mount } from '@vue/test-utils'
import MyComponent from '@/components/MyComponent.vue'
let wrapper
beforeAll(() => {
wrapper = mount(MyComponent, {
props: { initialCount: 5 }
})
})
afterAll(() => {
wrapper.unmount()
})
test('проверка текста', () => {
expect(wrapper.text()).toContain('5')
})
test('проверка кнопки', () => {
const button = wrapper.find('button')
button.trigger('click')
expect(wrapper.text()).toContain('6')
})
Использование beforeAll вместо beforeEach
предотвращает многократное создание экземпляра компонента, что особенно
важно при тяжелых или асинхронных компонентах.
Vue Test Utils предоставляет удобные методы для поиска элементов, но многократное обращение к DOM может быть избыточным. Для повышения эффективности можно кэшировать результаты поиска:
let wrapper
let button
beforeEach(() => {
wrapper = mount(MyComponent)
button = wrapper.find('button')
})
test('клик увеличивает счётчик', async () => {
await button.trigger('click')
expect(wrapper.text()).toContain('1')
})
Если тестов много, а структура компонента стабильна, можно создавать отдельный объект кэша для всех часто используемых селекторов:
const cache = {}
beforeEach(() => {
const wrapper = mount(MyComponent)
cache.wrapper = wrapper
cache.button = wrapper.find('button')
})
Асинхронные операции или вычисляемые свойства могут быть дорогими для повторного выполнения. В тестах можно сохранять их значения:
import { vi } from 'vitest'
const fetchData = vi.fn(async () => {
return Promise.resolve({ value: 42 })
})
let cachedData
beforeAll(async () => {
cachedData = await fetchData()
})
test('значение кэшированного ответа', () => {
expect(cachedData.value).toBe(42)
})
Такой подход уменьшает время выполнения тестового набора и обеспечивает стабильность результатов.
Vue использует реактивность для отслеживания изменений в данных. При
кэшировании компонентов или элементов важно учитывать, что состояние
wrapper сохраняется вместе с реактивными свойствами. Для
предотвращения нежелательных эффектов между тестами:
beforeAll только для неизменяемых
состояний.beforeEach, создавая свежий wrapper.wrapper.setProps, wrapper.setData.beforeEach(() => {
wrapper.setData({ count: 0 }) // сброс состояния
})
Для оптимизации больших компонентов используется
shallowMount, который рендерит компонент без дочерних
компонентов. Кэширование shallowMount особенно эффективно
при тестировании функционала родителя без необходимости рендерить
сложные дочерние компоненты.
import { shallowMount } from '@vue/test-utils'
import ParentComponent from '@/components/ParentComponent.vue'
let wrapper
beforeAll(() => {
wrapper = shallowMount(ParentComponent)
})
test('рендерим родителя', () => {
expect(wrapper.exists()).toBe(true)
})
afterAll для очистки кэша и
размонтирования компонентов.cache с разными уровнями: компоненты, элементы, данные,
моки.Кэширование в тестах Vue Test Utils позволяет повысить скорость, уменьшить нагрузку на систему и сделать тесты более детерминированными при правильной организации жизненного цикла компонентов и моков.