В Vue.js компоненты обмениваются данными через props. Когда props представляют собой объекты или массивы, тестирование их поведения требует особого внимания. Vue Test Utils предоставляет инструменты для точной проверки работы компонентов с такими сложными структурами данных.
Компонент может принимать props как объекты или массивы, например:
// Компонент
export default {
props: {
user: Object,
items: Array
},
template: `
<div>
<p>{{ user.name }}</p>
<ul>
<li v-for="item in items" :key="item.id">{{ item.label }}</li>
</ul>
</div>
`
};
При тестировании через Vue Test Utils можно передавать сложные
структуры в props при монтировании:
import { mount } from '@vue/test-utils';
import MyComponent from '@/components/MyComponent.vue';
const wrapper = mount(MyComponent, {
props: {
user: { name: 'Alice', age: 25 },
items: [
{ id: 1, label: 'Первый' },
{ id: 2, label: 'Второй' }
]
}
});
Важно: объектные и массивные props передаются по ссылке, поэтому любые изменения в тесте могут повлиять на исходные данные. Если нужно изолировать данные, их следует клонировать:
const userCopy = { ...user };
const itemsCopy = items.map(item => ({ ...item }));
Для проверки работы с объектными props удобно использовать методы
.props(), .text(), а также прямое обращение к
реактивным данным:
expect(wrapper.props('user')).toEqual({ name: 'Alice', age: 25 });
expect(wrapper.text()).toContain('Alice');
Если компонент изменяет внутреннюю копию объекта, необходимо
использовать wrapper.vm для доступа к реактивным
свойствам:
wrapper.vm.user.name = 'Bob';
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain('Bob');
Массивы требуют проверки как количества элементов, так и их содержимого:
const listItems = wrapper.findAll('li');
expect(listItems).toHaveLength(2);
expect(listItems[0].text()).toBe('Первый');
expect(listItems[1].text()).toBe('Второй');
Для динамических изменений массива используется метод
setProps или изменение реактивной копии:
wrapper.setProps({ items: [...wrapper.props('items'), { id: 3, label: 'Третий' }] });
await wrapper.vm.$nextTick();
expect(wrapper.findAll('li')).toHaveLength(3);
expect(wrapper.text()).toContain('Третий');
toBe. Для сравнения значений
используется toEqual.setProps корректно обновляет компонент.Vue.set или заменять весь объект/массив новым
экземпляром.Иногда требуется протестировать компонент независимо от исходных данных:
const wrapper = mount(MyComponent, {
props: {
user: jest.fn(() => ({ name: 'Mocked', age: 0 }))(),
items: []
}
});
Такой подход позволяет полностью контролировать поведение компонентных props без влияния внешних объектов.
Если компонент вычисляет значения на основе сложных props или
отслеживает их через watch, Vue Test Utils позволяет
имитировать изменения:
// Изменение массива
wrapper.setProps({ items: [{ id: 1, label: 'Обновлённый' }] });
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain('Обновлённый');
// Проверка реактивного watcher
wrapper.vm.user.age = 30;
await wrapper.vm.$nextTick();
expect(wrapper.vm.user.age).toBe(30);
Watcher срабатывает при любом изменении реактивной копии, но не при мутации исходного объекта, переданного напрямую без клонирования.
Для многослойных объектов часто используют глубокое клонирование перед тестом:
const deepClone = obj => JSON.parse(JSON.stringify(obj));
const wrapper = mount(MyComponent, {
props: { user: deepClone(originalUser) }
});
Это предотвращает непреднамеренные побочные эффекты между тестами.
.props(),
.text(), .findAll().setProps или полное обновление объекта.Эта методология обеспечивает корректное и детальное тестирование компонентов Vue при работе с объектными и массивными props, позволяя отслеживать их реактивные изменения и точное отображение в шаблоне.