При тестировании компонентов Vue, работающих с большими массивами данных, важно учитывать производительность и точность тестов. Простое рендеринг всего списка в тесте может привести к замедлению сборки и снижению стабильности тестов. Основные подходы включают срезание данных, использование моков и виртуализацию.
shallowMount для снижения нагрузкиshallowMount позволяет монтировать компонент без
рендеринга дочерних компонентов полностью. Это особенно полезно, если
список содержит вложенные компоненты:
import { shallowMount } from '@vue/test-utils';
import ItemList from '@/components/ItemList.vue';
const items = Array.from({ length: 1000 }, (_, i) => ({ id: i, name: `Item ${i}` }));
const wrapper = shallowMount(ItemList, {
props: { items }
});
// Проверка наличия нужного количества элементов
expect(wrapper.findAll('li')).toHaveLength(1000);
Ключевой момент: shallowMount не
предотвращает рендеринг элементов DOM, но сокращает нагрузку за счет
игнорирования дочерних компонентов, что ускоряет выполнение тестов.
Тестировать весь массив из тысячи элементов редко нужно. Часто достаточно проверить корректность работы на подмножестве данных:
const smallItems = items.slice(0, 10);
const wrapper = shallowMount(ItemList, {
props: { items: smallItems }
});
expect(wrapper.findAll('li')).toHaveLength(10);
Такой подход уменьшает количество создаваемых DOM-узлов и снижает время выполнения тестов.
Важно: выборка должна сохранять типичные сценарии использования: первый элемент, последний элемент, случайный элемент.
Если компонент вызывает методы для загрузки данных (API, Vuex), их стоит заменять моками. Это уменьшает зависимость тестов от внешних сервисов и ускоряет выполнение.
import { shallowMount } from '@vue/test-utils';
import ItemList from '@/components/ItemList.vue';
const fetchItemsMock = jest.fn(() => Array.from({ length: 1000 }, (_, i) => ({ id: i })));
const wrapper = shallowMount(ItemList, {
props: { fetchItems: fetchItemsMock }
});
expect(fetchItemsMock).toHaveBeenCalled();
Моки позволяют сфокусироваться на логике рендеринга и обработке данных, игнорируя реальные вызовы API.
Для рендеринга больших списков в реальном приложении часто
используется виртуализация (например,
vue-virtual-scroller). В тестах нужно учитывать, что не
весь список присутствует в DOM:
import { mount } from '@vue/test-utils';
import VirtualList from '@/components/VirtualList.vue';
const wrapper = mount(VirtualList, {
props: { items }
});
// Проверка, что в DOM отрендерились только видимые элементы
expect(wrapper.findAll('li').length).toBeLessThan(items.length);
Преимущество: тесты остаются быстрыми, а поведение компонента проверяется корректно для видимых элементов.
findAll и фильтрацииПри работе с большим списком не рекомендуется выполнять глубокий поиск по всему DOM. Вместо этого используют фильтры и селекторы:
const visibleItems = wrapper.findAll('li').filter(node => node.isVisible());
expect(visibleItems.length).toBeLessThanOrEqual(50);
Совет: избегать использования глобального
wrapper.html() для сравнения больших списков, так как это
замедляет тест и увеличивает риск ложноположительных результатов.
Vue Test Utils позволяет проверять реактивные изменения массива через
setProps или обновление состояния:
wrapper.setProps({ items: items.slice(0, 20) });
await wrapper.vm.$nextTick();
expect(wrapper.findAll('li')).toHaveLength(20);
Важно: при работе с большими списками следует
использовать асинхронные ожидания
(await wrapper.vm.$nextTick()), чтобы убедиться, что DOM
обновился после изменения данных.
Если требуется проверка различных сценариев с разными размерами
списка, удобно использовать describe.each или
test.each:
const sizes = [10, 100, 1000];
test.each(sizes)('рендер %i элементов', async (size) => {
const wrapper = shallowMount(ItemList, {
props: { items: Array.from({ length: size }, (_, i) => ({ id: i })) }
});
expect(wrapper.findAll('li').length).toBe(size);
});
Такой подход уменьшает дублирование кода и систематизирует проверку производительности.
Для больших списков не всегда требуется проверять текст каждого элемента. Достаточно проверить ключевые элементы или шаблон текста:
expect(wrapper.find('li:first-child').text()).toBe('Item 0');
expect(wrapper.find('li:last-child').text()).toBe(`Item ${items.length - 1}`);
Это ускоряет тесты и делает их стабильнее при изменении внутренних данных списка.
Эти методы совместно позволяют писать быстрые, стабильные и читаемые тесты для компонентов Vue, работающих с большими массивами данных, минимизируя нагрузку на тестовый раннер и обеспечивая проверку критической функциональности без лишних операций.