В процессе тестирования компонентов Vue, взаимодействующих с API, критически важно проверять, как компоненты реагируют на разные HTTP-статусы. Vue Test Utils предоставляет средства для изоляции компонента и контроля над внешними зависимостями, такими как HTTP-запросы. Основной подход заключается в мокировании запросов и проверке поведения компонента при различных ответах сервера.
Наиболее распространённый способ — использование сторонних библиотек для мокирования, таких как axios-mock-adapter для Axios или fetch-mock для fetch. Это позволяет подменять реальные сетевые вызовы фиктивными данными и статусами.
Пример с Axios и Jest:
import { mount } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import MyComponent from '@/components/MyComponent.vue';
describe('MyComponent', () => {
let mock;
beforeEach(() => {
mock = new MockAdapter(axios);
});
afterEach(() => {
mock.restore();
});
it('обрабатывает статус 200', async () => {
mock.onGet('/api/data').reply(200, { message: 'OK' });
const wrapper = mount(MyComponent);
await wrapper.vm.fetchData();
expect(wrapper.text()).toContain('OK');
});
it('обрабатывает статус 404', async () => {
mock.onGet('/api/data').reply(404);
const wrapper = mount(MyComponent);
await wrapper.vm.fetchData();
expect(wrapper.text()).toContain('Ошибка: 404');
});
it('обрабатывает статус 500', async () => {
mock.onGet('/api/data').reply(500);
const wrapper = mount(MyComponent);
await wrapper.vm.fetchData();
expect(wrapper.text()).toContain('Ошибка сервера');
});
});
Ключевой момент — использование метода
reply(status, data) для задания конкретного HTTP-кода и
ответа. Это позволяет проверить, как компонент реагирует на успешные и
ошибочные ответы.
Компонент, работающий с API, обычно реализует одну из следующих стратегий:
Пример Vue-компонента:
<template>
<div>
<p v-if="error">{{ error }}</p>
<p v-else-if="data">{{ data.message }}</p>
<p v-else>Загрузка...</p>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
data: null,
error: null,
};
},
methods: {
async fetchData() {
try {
const response = await axios.get('/api/data');
this.data = response.data;
this.error = null;
} catch (e) {
if (e.response) {
if (e.response.status >= 500) {
this.error = 'Ошибка сервера';
} else if (e.response.status >= 400) {
this.error = `Ошибка: ${e.response.status}`;
}
} else {
this.error = 'Неизвестная ошибка';
}
}
},
},
};
</script>
Важно тестировать не только данные, но и состояние
компонента после ошибок. Vue Test Utils позволяет проверять DOM после
асинхронных операций, используя await nextTick() или
await wrapper.vm.$nextTick().
Асинхронные запросы требуют ожидания обновления DOM перед проверкой:
import { nextTick } from 'vue';
it('отображает сообщение об ошибке после 404', async () => {
mock.onGet('/api/data').reply(404);
const wrapper = mount(MyComponent);
await wrapper.vm.fetchData();
await nextTick();
expect(wrapper.text()).toContain('Ошибка: 404');
});
nextTick() гарантирует, что Vue завершил все реактивные
обновления, прежде чем проверять состояние компонента.
Чтобы избежать дублирования кода, можно использовать
test.each или аналогичные конструкции для проверки
множества статусов:
test.each([
[200, 'OK', null],
[404, null, 'Ошибка: 404'],
[500, null, 'Ошибка сервера'],
])('статус %i обрабатывается корректно', async (status, message, error) => {
mock.onGet('/api/data').reply(status, { message });
const wrapper = mount(MyComponent);
await wrapper.vm.fetchData();
await nextTick();
if (message) {
expect(wrapper.text()).toContain(message);
}
if (error) {
expect(wrapper.text()).toContain(error);
}
});
Такой подход повышает читаемость тестов и упрощает добавление новых случаев.
Для проверки вызовов методов и логики обработки можно использовать
jest.spyOn:
it('вызывает метод fetchData при создании', async () => {
const spy = jest.spyOn(MyComponent.methods, 'fetchData');
mount(MyComponent);
expect(spy).toHaveBeenCalled();
spy.mockRestore();
});
Это позволяет удостовериться, что компонент инициирует запросы именно в нужный момент жизненного цикла.
Некоторые API могут возвращать статусы вне стандартного диапазона или комбинацию данных и кода ошибки. В таких случаях важно тестировать:
response в
ошибке.Пример обработки таймаута:
mock.onGet('/api/data').timeout();
const wrapper = mount(MyComponent);
await wrapper.vm.fetchData();
await nextTick();
expect(wrapper.text()).toContain('Неизвестная ошибка');
Использование этих методик обеспечивает полное покрытие реакций компонента на HTTP-статусы, позволяет выявлять баги в логике обработки ошибок и повышает стабильность приложений Vue, особенно в компонентах, тесно связанных с внешними API.