Composition API во Vue.js предоставляет мощные возможности для
организации логики компонентов с помощью функций setup(),
реактивных переменных и эффектов. Тестирование таких компонентов требует
понимания, как эти реактивные сущности взаимодействуют с рендерингом и
поведением приложения.
В Composition API состояние компонента обычно создаётся через
ref() или reactive(). Для тестирования важно
проверять не только начальные значения, но и их реакцию на
изменения.
import { ref } from 'vue';
export function useCounter() {
const count = ref(0);
const increment = () => count.value++;
return { count, increment };
}
Тестирование такой функции может выполняться без рендера компонента, используя прямое обращение к возвращаемым значениям:
import { useCounter } from './useCounter';
test('increment увеличивает count', () => {
const { count, increment } = useCounter();
expect(count.value).toBe(0);
increment();
expect(count.value).toBe(1);
});
Ключевой момент — ref хранит значение в поле
.value, и именно его нужно проверять в тестах.
setup()Компоненты, использующие setup(), можно тестировать
через рендеринг с помощью библиотек вроде Vue Test Utils. Основная
задача — проверять, как состояние влияет на DOM и взаимодействие
пользователя.
import { mount } from '@vue/test-utils';
import CounterComponent from './CounterComponent.vue';
test('отображение и увеличение счётчика', async () => {
const wrapper = mount(CounterComponent);
expect(wrapper.text()).toContain('0');
await wrapper.find('button').trigger('click');
expect(wrapper.text()).toContain('1');
});
Composition API поощряет создание reusable функций
(composables). Для таких функций тестирование проще, так
как они не зависят от DOM:
export function useToggle(initial = false) {
const state = ref(initial);
const toggle = () => state.value = !state.value;
return { state, toggle };
}
Тестирование:
import { useToggle } from './useToggle';
test('toggle меняет состояние', () => {
const { state, toggle } = useToggle();
expect(state.value).toBe(false);
toggle();
expect(state.value).toBe(true);
});
Асинхронные операции в setup() могут выполняться через
watchEffect, onMounted или обычные функции с
async/await. Для тестирования таких сценариев важно
использовать асинхронные тесты.
import { ref, onMounted } from 'vue';
export function useFetchData(fetcher) {
const data = ref(null);
const error = ref(null);
onMounted(async () => {
try {
data.value = await fetcher();
} catch (e) {
error.value = e;
}
});
return { data, error };
}
Тестирование:
import { useFetchData } from './useFetchData';
import { nextTick } from 'vue';
test('fetchData получает данные', async () => {
const fetcher = jest.fn().mockResolvedValue('result');
const { data } = useFetchData(fetcher);
await nextTick();
expect(data.value).toBe('result');
});
Использование nextTick гарантирует, что реактивные
обновления завершились перед проверкой значений.
Компоненты с Composition API часто используют внешние сервисы или composables. Для тестирования необходимо изолировать такие зависимости через мок-функции:
jest.mock('./api', () => ({
fetchUser: jest.fn().mockResolvedValue({ name: 'Alice' })
}));
Это позволяет тестировать логику компонента без реальных сетевых запросов и контролировать возвращаемые данные.
Для сложных компонентов важно проверять взаимодействие реактивного
состояния с шаблоном. Vue Test Utils предоставляет методы
find, text, trigger, а также
доступ к vm для проверки внутренних данных:
const wrapper = mount(Component);
wrapper.vm.someRef.value = 42;
await nextTick();
expect(wrapper.text()).toContain('42');
setup()
с рендером. Подтверждают корректность DOM и взаимодействий.nextTick для реактивных
обновлений: гарантирует корректность проверок после изменений
состояния.Тестирование Composition API требует внимания к реактивности и асинхронности. Изоляция логики через composables делает код более предсказуемым и легко проверяемым, что позволяет создавать надёжные и масштабируемые приложения на Vue.js.