Unit тестирование с Jest

Unit тестирование позволяет проверять отдельные компоненты приложения на корректность их работы без необходимости запускать всё приложение целиком. В экосистеме Vue.js чаще всего используют Jest — мощный и гибкий тест-раннер с поддержкой моков, снапшотов и асинхронного кода.


Установка и настройка Jest

Для проектов на Vue 3 рекомендуется использовать официальную интеграцию через @vue/test-utils и Jest:

npm install --save-dev @vue/test-utils jest babel-jest vue-jest
  • @vue/test-utils — библиотека для тестирования Vue-компонентов.
  • jest — сам тест-раннер.
  • babel-jest — для поддержки современного JavaScript.
  • vue-jest — позволяет Jest понимать .vue файлы.

Конфигурация Jest может храниться в файле jest.config.js:

module.exports = {
  moduleFileExtensions: ['js', 'json', 'vue'],
  transform: {
    '^.+\\.vue$': 'vue-jest',
    '^.+\\.js$': 'babel-jest'
  },
  testEnvironment: 'jsdom'
};
  • moduleFileExtensions — расширения файлов, которые Jest будет обрабатывать.
  • transform — настройка транспилеров для Vue и JS.
  • testEnvironment: 'jsdom' — эмулирует браузерное окружение.

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

Создание простого компонента

<template>
  <button @click="increment">{{ count }}</button>
</template>

<script>
export default {
  data() {
    return {
      count: 0
    };
  },
  methods: {
    increment() {
      this.count++;
    }
  }
};
</script>

Простой unit-тест

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

describe('Counter.vue', () => {
  it('отображает начальное значение', () => {
    const wrapper = mount(Counter);
    expect(wrapper.text()).toContain('0');
  });

  it('увеличивает счетчик по клику', async () => {
    const wrapper = mount(Counter);
    await wrapper.find('button').trigger('click');
    expect(wrapper.text()).toContain('1');
  });
});

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

  • mount полностью рендерит компонент с его шаблоном.
  • find('button') ищет DOM-элемент внутри компонента.
  • trigger('click') симулирует событие.
  • async/await необходим для корректного ожидания обновления DOM.

Моки и шпионы

Для тестирования методов или внешних зависимостей используются моки и шпионы.

const mockFn = jest.fn();
mockFn('test');
expect(mockFn).toHaveBeenCalledWith('test');

В Vue компонентах можно мокать пропсы, методы или внешние сервисы:

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

const mockApi = { fetchUser: jest.fn(() => Promise.resolve({ name: 'Alice' })) };

describe('UserProfile.vue', () => {
  it('загружает пользователя', async () => {
    const wrapper = mount(UserProfile, {
      global: {
        mocks: { $api: mockApi }
      }
    });
    await wrapper.vm.loadUser();
    expect(wrapper.text()).toContain('Alice');
  });
});
  • global.mocks позволяет подменять глобальные объекты Vue.
  • Асинхронные методы тестируются через await.

Снапшоты

Снапшот-тестирование позволяет проверять неизменность структуры компонента:

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

test('рендер кнопки совпадает со снимком', () => {
  const wrapper = mount(Button);
  expect(wrapper.html()).toMatchSnapshot();
});

При первом запуске Jest создаёт файл снапшота. При последующих тестах сравнивается актуальная разметка с сохранённой.

Рекомендации:

  • Использовать снапшоты для компонентов без сложной логики.
  • Не использовать для динамических данных, которые часто меняются.

Асинхронное тестирование

Асинхронные операции в компонентах (например, fetch-запросы) требуют корректного ожидания:

it('получает данные с сервера', async () => {
  const wrapper = mount(DataComponent);
  await wrapper.vm.fetchData();
  await wrapper.vm.$nextTick();
  expect(wrapper.text()).toContain('Данные получены');
});
  • await wrapper.vm.$nextTick() гарантирует обновление DOM перед проверкой.

Практические советы

  1. Изолированное тестирование — каждый тест должен проверять только один аспект компонента.
  2. Моки для внешних сервисов — избегают реальных сетевых запросов.
  3. Чистота тестов — использовать beforeEach и afterEach для сброса состояния.
  4. Совмещение снапшотов и unit-тестов — снапшоты проверяют структуру, unit-тесты — логику.
  5. Асинхронные методы — всегда использовать async/await и nextTick.

Unit тестирование с Jest позволяет создавать надёжные Vue-приложения, минимизируя ошибки при изменении кода и упрощая рефакторинг компонентов. Такой подход обеспечивает предсказуемость поведения и повышает качество проекта.