Тестирование с axios

Подключение и настройка

Для тестирования компонентов Vue, которые используют axios для HTTP-запросов, необходимо изолировать сетевое взаимодействие. Это позволяет проверять логику компонентов без реального обращения к серверу, предотвращая зависимость тестов от внешних API.

На практике чаще всего используется mocking axios с помощью Jest:

import { mount } from '@vue/test-utils';
import axios from 'axios';
import Component from '@/components/Component.vue';

jest.mock('axios');

После вызова jest.mock('axios') все методы axios становятся Jest-моками, что позволяет управлять их поведением и проверять вызовы.


Мокаем ответы сервера

Основной подход заключается в настройке возвращаемого значения методов axios.get, axios.post и других:

axios.get.mockResolvedValue({
  data: { message: 'Success' }
});

axios.post.mockRejectedValue(new Error('Network Error'));
  • mockResolvedValue — имитация успешного ответа с данными.
  • mockRejectedValue — имитация ошибки запроса, что позволяет тестировать обработку ошибок.

Для более сложных сценариев можно использовать mockImplementation, чтобы реализовать динамическую логику:

axios.get.mockImplementation((url) => {
  if (url === '/api/user') {
    return Promise.resolve({ data: { id: 1, name: 'Alice' } });
  }
  return Promise.reject(new Error('Not Found'));
});

Тестирование методов компонентов

Компоненты, использующие axios, обычно вызывают его внутри методов или хуков жизненного цикла, например mounted или created.

Пример теста метода, который загружает данные при монтировании:

test('загружает данные при монтировании', async () => {
  axios.get.mockResolvedValue({ data: { name: 'Vue' } });
  
  const wrapper = mount(Component);
  
  // Дожидаемся завершения всех асинхронных операций
  await wrapper.vm.$nextTick();
  
  expect(axios.get).toHaveBeenCalledWith('/api/data');
  expect(wrapper.text()).toContain('Vue');
});

Ключевые моменты:

  • Асинхронные операции требуют await wrapper.vm.$nextTick() или flushPromises.
  • Проверка вызова axios с правильными параметрами выполняется через toHaveBeenCalledWith.
  • Отдельно проверяется обработка состояния компонента после ответа сервера.

Тестирование ошибок и fallback-логики

Компоненты должны корректно реагировать на ошибки сетевых запросов:

test('обрабатывает ошибки запроса', async () => {
  axios.get.mockRejectedValue(new Error('Server Error'));

  const wrapper = mount(Component);

  await wrapper.vm.$nextTick();

  expect(wrapper.text()).toContain('Ошибка загрузки данных');
});

Важно проверять не только факт вызова запроса, но и корректность отображения ошибок или fallback-контента в шаблоне.


Использование flush-promises для упрощения тестов

Для ожидания завершения всех промисов можно подключить библиотеку flush-promises:

import flushPromises from 'flush-promises';

test('корректно обрабатывает данные с сервера', async () => {
  axios.get.mockResolvedValue({ data: { value: 42 } });

  const wrapper = mount(Component);

  await flushPromises();

  expect(wrapper.vm.data.value).toBe(42);
  expect(wrapper.text()).toContain('42');
});

flush-promises особенно полезен, когда в компоненте несколько последовательных асинхронных вызовов.


Мокаем axios глобально

Для крупных проектов удобнее создать глобальный mock axios, чтобы не дублировать настройку в каждом тесте:

// __mocks__/axios.js
export default {
  get: jest.fn(),
  post: jest.fn(),
  put: jest.fn(),
  delete: jest.fn()
};

Jest автоматически подхватывает этот файл при jest.mock('axios'). Это обеспечивает единообразие моков и упрощает поддержку тестов.


Интеграция с Vuex и axios

При использовании Vuex часто actions делают HTTP-запросы через axios. Тестирование таких actions включает мокацию axios и проверку мутаций:

import { actions } from '@/store/module';
import axios from 'axios';

jest.mock('axios');

test('action fetchUser коммитит мутацию с данными', async () => {
  const commit = jest.fn();
  axios.get.mockResolvedValue({ data: { id: 1, name: 'Alice' } });

  await actions.fetchUser({ commit });

  expect(commit).toHaveBeenCalledWith('SET_USER', { id: 1, name: 'Alice' });
});

Таким образом, тестирование действий Vuex с axios строится на мокации HTTP-запросов и проверке вызовов commit.


Советы по структурированию тестов с axios

  • Каждый тест должен быть самодостаточным, с собственным мок-ответом.
  • Проверять как успешные ответы, так и ошибки сети.
  • Для сложных сценариев можно использовать jest.spyOn, чтобы отслеживать вызовы определённых методов axios без глобальной мокации.
  • Асинхронные операции требуют обязательного ожидания промисов (await wrapper.vm.$nextTick() или flushPromises).
  • В больших компонентах выделять отдельные методы для запросов, чтобы их легче тестировать отдельно.

Такой подход обеспечивает детальное покрытие компонентов и Vuex-модулей, использующих axios, без зависимости от внешних API и реальных сетевых условий.