Асинхронные компоненты в Vue позволяют загружать части приложения динамически, снижая размер начальной сборки и ускоряя загрузку страницы. При тестировании таких компонентов важно учитывать особенности их поведения: рендер происходит не мгновенно, а после завершения асинхронной операции.
Асинхронный компонент создаётся с помощью функции, возвращающей промис:
const AsyncComponent = () => import('./MyComponent.vue');
Vue автоматически обрабатывает промис и рендерит компонент после его разрешения. В тестах необходимо дождаться завершения этой загрузки.
Vue Test Utils предоставляет метод mount, но для
асинхронных компонентов требуется дополнительное ожидание рендера:
import { mount } from '@vue/test-utils';
import AsyncComponent from '@/components/AsyncComponent.vue';
import { nextTick } from 'vue';
test('рендер асинхронного компонента', async () => {
const wrapper = mount(AsyncComponent);
// Асинхронная загрузка компонента требует ожидания следующего "тикa"
await nextTick();
expect(wrapper.text()).toContain('Контент асинхронного компонента');
});
Ключевой момент: после mount компонент
ещё не полностью инициализирован. Использование nextTick
или flushPromises позволяет дождаться рендера.
flush-promisesДля удобного управления асинхронностью часто применяется библиотека
flush-promises. Она позволяет дождаться всех разрешённых
промисов:
import flushPromises from 'flush-promises';
import { mount } from '@vue/test-utils';
import AsyncComponent from '@/components/AsyncComponent.vue';
test('асинхронный компонент с fetch', async () => {
const wrapper = mount(AsyncComponent);
await flushPromises(); // ожидание всех промисов внутри компонента
expect(wrapper.text()).toContain('Данные загружены');
});
flushPromises особенно полезен при работе с
компонентами, которые делают HTTP-запросы или используют Vuex actions
асинхронно.
shallowMountПри использовании shallowMount асинхронные дочерние
компоненты заменяются заглушками, что ускоряет тестирование:
import { shallowMount } from '@vue/test-utils';
import ParentComponent from '@/components/ParentComponent.vue';
import flushPromises from 'flush-promises';
test('родительский компонент рендерит асинхронный дочерний', async () => {
const wrapper = shallowMount(ParentComponent);
await flushPromises();
expect(wrapper.findComponent({ name: 'AsyncComponent' }).exists()).toBe(true);
});
Особенность: shallowMount полезен для
изоляции тестируемого компонента от зависимостей.
Для управления асинхронным поведением можно использовать jest mocks:
jest.mock('@/api/fetchData', () => ({
fetchData: jest.fn(() => Promise.resolve('Моковые данные'))
}));
import AsyncComponent from '@/components/AsyncComponent.vue';
import { mount } from '@vue/test-utils';
import flushPromises from 'flush-promises';
test('асинхронный компонент получает моковые данные', async () => {
const wrapper = mount(AsyncComponent);
await flushPromises();
expect(wrapper.text()).toContain('Моковые данные');
});
Такой подход позволяет полностью контролировать асинхронные операции и делает тесты детерминированными.
Асинхронные методы компонента могут быть вызваны через события:
test('асинхронный метод вызывается по клику', async () => {
const wrapper = mount(AsyncComponent);
await wrapper.find('button').trigger('click');
await flushPromises();
expect(wrapper.text()).toContain('Результат после клика');
});
Важно: всегда использовать await перед
проверкой состояния после асинхронного действия.
Компоненты Vue имеют жизненные циклы (mounted,
created), которые могут содержать асинхронные операции. Для
корректного тестирования необходимо:
flushPromises
или nextTick.Пример с асинхронным mounted:
mounted() {
this.loadData();
},
methods: {
async loadData() {
this.data = await fetchData();
}
}
Тестирование:
test('данные загружаются при mounted', async () => {
const wrapper = mount(AsyncComponent);
await flushPromises();
expect(wrapper.vm.data).toBe('Загруженные данные');
});
await для ожидания завершения
асинхронных операций.flushPromises удобен для промисов внутри методов и
жизненных циклов.nextTick помогает дождаться обновления DOM после
реактивных изменений.shallowMount ускоряет тесты при наличии дочерних
компонентов.Асинхронное тестирование требует дисциплины в управлении ожиданиями, но обеспечивает надёжное покрытие и контроль над поведением компонентов.