В Vue.js computed свойства представляют собой реактивные
вычисления, которые автоматически обновляются при изменении зависимых
данных (data или других реактивных источников).
Тестирование computed требует проверки, что при изменении
исходных данных значение вычисляемого свойства корректно
пересчитывается. Vue Test Utils предоставляет инструменты для изоляции
компонентов и проверки реактивного поведения.
computed в Vuecomputed свойства:
computed или
props в качестве зависимостей.Пример компонента:
<template>
<div>{{ fullName }}</div>
</template>
<script>
export default {
data() {
return {
firstName: 'Иван',
lastName: 'Иванов'
};
},
computed: {
fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
};
</script>
Здесь fullName зависит от firstName и
lastName. Любое их изменение должно автоматически обновлять
fullName.
Основная задача — убедиться, что computed корректно реагирует на
изменения данных. В Vue Test Utils доступны методы mount и
shallowMount, которые позволяют получить экземпляр
компонента (wrapper.vm) и изменять его реактивные свойства
напрямую.
Пример теста с Jest:
import { mount } from '@vue/test-utils';
import UserName from '@/components/UserName.vue';
describe('UserName.vue', () => {
it('обновляет fullName при изменении firstName', async () => {
const wrapper = mount(UserName);
expect(wrapper.vm.fullName).toBe('Иван Иванов');
wrapper.vm.firstName = 'Пётр';
await wrapper.vm.$nextTick();
expect(wrapper.vm.fullName).toBe('Пётр Иванов');
});
it('обновляет fullName при изменении lastName', async () => {
const wrapper = mount(UserName);
wrapper.vm.lastName = 'Петров';
await wrapper.vm.$nextTick();
expect(wrapper.vm.fullName).toBe('Иван Петров');
});
});
Ключевые моменты:
wrapper.vm.await wrapper.vm.$nextTick() гарантирует, что Vue завершил
обновление вычисляемых свойств.wrapper.vm.fullName.Если computed зависит от других computed,
проверка аналогична, но нужно учитывать цепочку зависимостей.
Например:
computed: {
initials() {
return `${this.firstName[0]}${this.lastName[0]}`;
},
fullNameWithInitials() {
return `${this.fullName} (${this.initials})`;
}
}
Тест:
it('обновляет fullNameWithInitials при изменении данных', async () => {
const wrapper = mount(UserName);
wrapper.vm.firstName = 'Пётр';
wrapper.vm.lastName = 'Петров';
await wrapper.vm.$nextTick();
expect(wrapper.vm.fullNameWithInitials).toBe('Пётр Петров (ПП)');
});
Vue использует виртуальный DOM и асинхронные обновления. Без
await wrapper.vm.$nextTick() тест может проверять старое
значение computed, поскольку обновление еще не произошло. В
сложных компонентах с несколькими реактивными цепочками
$nextTick() становится критически важным.
Кроме прямой проверки wrapper.vm, можно тестировать
влияние computed на шаблон:
it('отображает обновлённый fullName в шаблоне', async () => {
const wrapper = mount(UserName);
wrapper.vm.firstName = 'Алексей';
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain('Алексей Иванов');
});
Такой подход проверяет не только реактивность, но и корректный рендер, что особенно важно для интеграционных тестов.
mount с разными начальными значениями для проверки
граничных случаев.Computed, зависящие от объектов или массивов, требуют особого внимания, так как Vue отслеживает реактивность на уровне свойств. Пример:
data() {
return {
items: [{ name: 'apple' }, { name: 'banana' }]
};
},
computed: {
itemNames() {
return this.items.map(item => item.name).join(', ');
}
}
Тест:
it('обновляет itemNames при добавлении элемента', async () => {
const wrapper = mount(ComponentWithItems);
wrapper.vm.items.push({ name: 'orange' });
await wrapper.vm.$nextTick();
expect(wrapper.vm.itemNames).toBe('apple, banana, orange');
});
Важно: изменения по ссылке требуют реактивных методов Vue
(push, splice) или использования
Vue.set в Vue 2.
Проверка computed через изменение data обеспечивает уверенность в
правильной работе реактивной системы. Комбинация прямой проверки через
wrapper.vm и проверки рендера шаблона покрывает как
внутреннее состояние, так и пользовательский интерфейс.