Computed свойства в Vue представляют собой реактивные вычисляемые значения, которые зависят от данных компонента и автоматически пересчитываются при их изменении. Тестирование таких свойств требует понимания как реактивности Vue, так и особенностей работы Vue Test Utils.
Основное отличие: computed свойства кэшируются на основе своих зависимостей, тогда как методы вызываются каждый раз при рендеринге. Это означает, что тестирование computed должно учитывать:
Для тестирования computed свойств используется mount или shallowMount из Vue Test Utils. ShallowMount позволяет изолировать компонент, избегая рендеринга дочерних компонентов, что удобно для юнит-тестов.
import { shallowMount } from '@vue/test-utils';
import ComponentWithComputed from '@/components/ComponentWithComputed.vue';
const wrapper = shallowMount(ComponentWithComputed);
Самый простой случай — проверка возвращаемого значения computed свойства на основе текущего состояния data.
it('правильно вычисляет полное имя', () => {
const wrapper = shallowMount(ComponentWithComputed, {
data() {
return { firstName: 'Иван', lastName: 'Петров' };
}
});
expect(wrapper.vm.fullName).toBe('Иван Петров');
});
Здесь fullName — computed свойство, зависящее от
firstName и lastName.
Computed свойства должны автоматически обновляться при изменении зависимостей. Для проверки этого изменяют data компонента и проверяют новое значение computed свойства.
it('обновляет fullName при изменении firstName', async () => {
const wrapper = shallowMount(ComponentWithComputed, {
data() {
return { firstName: 'Иван', lastName: 'Петров' };
}
});
wrapper.setData({ firstName: 'Алексей' });
await wrapper.vm.$nextTick();
expect(wrapper.vm.fullName).toBe('Алексей Петров');
});
Ключевой момент: после изменения данных всегда
следует ожидать завершения реактивного цикла с помощью
await wrapper.vm.$nextTick(), иначе computed свойство может
ещё не обновиться.
Computed свойства могут содержать не только геттер, но и сеттер. В таком случае тестирование должно проверять оба сценария: чтение и запись.
computed: {
fullName: {
get() {
return `${this.firstName} ${this.lastName}`;
},
set(value) {
const names = value.split(' ');
this.firstName = names[0];
this.lastName = names[1];
}
}
}
Тест геттера:
expect(wrapper.vm.fullName).toBe('Иван Петров');
Тест сеттера:
wrapper.vm.fullName = 'Алексей Сидоров';
await wrapper.vm.$nextTick();
expect(wrapper.vm.firstName).toBe('Алексей');
expect(wrapper.vm.lastName).toBe('Сидоров');
Иногда одно computed свойство зависит от другого. В таких случаях важно проверять последовательное обновление.
computed: {
greeting() {
return `Привет, ${this.fullName}`;
},
fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
Тестирование:
wrapper.setData({ firstName: 'Мария' });
await wrapper.vm.$nextTick();
expect(wrapper.vm.fullName).toBe('Мария Петров');
expect(wrapper.vm.greeting).toBe('Привет, Мария Петров');
Computed свойства часто зависят от props. В таких случаях для теста
используется опция propsData.
const wrapper = shallowMount(ComponentWithComputed, {
propsData: { basePrice: 100 }
});
expect(wrapper.vm.priceWithTax).toBe(120); // computed добавляет 20% налог
Изменение prop и проверка реактивности:
await wrapper.setProps({ basePrice: 200 });
expect(wrapper.vm.priceWithTax).toBe(240);
Если computed свойство использует методы компонента, можно использовать jest.spyOn для отслеживания вызовов.
jest.spyOn(wrapper.vm, 'calculateDiscount');
wrapper.vm.discountedPrice;
expect(wrapper.vm.calculateDiscount).toHaveBeenCalled();
Это помогает убедиться, что внутри computed свойства вызываются нужные функции.
await wrapper.vm.$nextTick().Тщательное тестирование computed свойств повышает надежность компонентов, предотвращает ошибки в реактивных зависимостях и гарантирует корректность бизнес-логики, встроенной в вычисляемые значения.