Пошаговое выполнение тестов

Enzyme — это популярная библиотека для тестирования компонентов React, которая предоставляет API для рендеринга, поиска элементов, симуляции событий и проверки состояния компонентов. Для написания качественных тестов с использованием Enzyme необходимо понимать последовательность действий, которые позволяют выполнить тесты корректно. Рассмотрим поэтапное выполнение тестов с Enzyme, начиная с базовых концепций до более сложных случаев.

1. Установка Enzyme и зависимостей

Для начала необходимо установить саму библиотеку Enzyme и несколько вспомогательных пакетов, которые обеспечат интеграцию с выбранным тестовым фреймворком, например, Jest.

npm install --save enzyme enzyme-adapter-react-16 jest

Затем следует настроить Enzyme для работы с React. Для этого создаётся файл конфигурации, в котором подключается адаптер для React:

import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

configure({ adapter: new Adapter() });

Этот код гарантирует, что Enzyme будет правильно работать с React-компонентами и тестировать их.

2. Рендеринг компонентов

Основной задачей при тестировании является рендеринг компонента и последующая проверка его работы. Enzyme предоставляет несколько методов рендеринга:

  • shallow — для поверхностного рендеринга компонента, без рендеринга дочерних компонентов.
  • mount — для полноценного рендеринга компонента с его дочерними элементами, что важно при тестировании компонентов с состоянием.
  • render — для рендеринга компонента в виде обычного HTML, что подходит для тестирования с использованием jQuery.

Пример рендеринга компонента с использованием метода shallow:

import { shallow } from 'enzyme';
import MyComponent from './MyComponent';

describe('<MyComponent />', () => {
  it('рендерится корректно', () => {
    const wrapper = shallow(<MyComponent />);
    expect(wrapper).toMatchSnapshot();
  });
});

В данном примере используется метод toMatchSnapshot, чтобы сравнить текущий вывод компонента с предыдущим снимком.

3. Тестирование событий

Один из важных аспектов тестирования — это симуляция пользовательских событий, таких как клики, ввод текста, наведение мыши и другие. Enzyme предоставляет функцию simulate, которая позволяет симулировать события на выбранных элементах.

Пример симуляции клика на кнопке:

it('вызывает обработчик клика', () => {
  const onCl ick = jest.fn();
  const wrapper = shallow(<button onCl ick={onClick}>Click me</button>);
  wrapper.simulate('click');
  expect(onClick).toHaveBeenCalled();
});

Здесь создаётся фейковая функция onClick, которая проверяется на вызов после симуляции клика.

4. Работа с состоянием компонента

Enzyme позволяет тестировать компоненты, у которых есть состояние. Для этого используется метод .state(), который позволяет получить текущее состояние компонента.

Пример проверки состояния компонента:

it('меняет состояние при клике', () => {
  const wrapper = shallow(<MyComponent />);
  expect(wrapper.state().isClicked).toBe(false);
  wrapper.find('button').simulate('click');
  expect(wrapper.state().isClicked).toBe(true);
});

В данном примере проверяется, что состояние компонента изменяется после клика на кнопку.

5. Проверка пропсов

Пропсы компонентов могут изменяться в процессе их рендеринга. Для их проверки используется метод .props(), который позволяет извлечь все пропсы компонента.

Пример проверки пропсов компонента:

it('получает правильный пропс', () => {
  const wrapper = shallow(<MyComponent name="John" />);
  expect(wrapper.props().name).toBe('John');
});

Здесь проверяется, что переданный пропс name имеет значение “John”.

6. Мокирование функций и API

Часто возникает необходимость замены реальных функций или API на моки, чтобы тесты не зависели от внешних факторов. Jest предоставляет возможность создания мок-функций, которые могут быть использованы в тестах.

Пример мокирования API:

it('вызывает API', () => {
  const apiMock = jest.fn().mockReturnValue(Promise.resolve('response'));
  const wrapper = shallow(<MyComponent fetchData={apiMock} />);
  
  wrapper.instance().fetchData();
  
  expect(apiMock).toHaveBeenCalled();
});

В данном случае мокируется функция API, и проверяется, что она была вызвана.

7. Использование асинхронных функций

Для тестирования асинхронных операций, таких как запросы к серверу или отложенные действия, необходимо использовать асинхронные методы Jest. Enzyme позволяет тестировать компоненты с асинхронными операциями, используя методы async/await.

Пример асинхронного теста:

it('загружает данные асинхронно', async () => {
  const wrapper = shallow(<MyComponent />);
  await wrapper.instance().fetchData();
  wrapper.update();
  expect(wrapper.state().data).toBe('response');
});

В этом примере данные загружаются асинхронно, и после завершения операции обновляется состояние компонента.

8. Снимки (Snapshots)

Снимки позволяют проверять, что визуальное представление компонента не изменяется со временем. Jest и Enzyme предлагают удобный способ работы с этим методом. Важно помнить, что снимки должны обновляться осознанно, чтобы не нарушить корректность тестов.

Пример использования снимков:

it('снимок компонента', () => {
  const wrapper = shallow(<MyComponent />);
  expect(wrapper).toMatchSnapshot();
});

Если компонент изменится, Jest предложит обновить снимок, чтобы отразить эти изменения.

9. Погружение в глубокие тесты с mount

Метод mount используется для рендеринга компонентов с их дочерними элементами. Это полезно при тестировании сложных компонентов, взаимодействующих с состоянием или жизненным циклом. Он позволяет делать более точные проверки, чем поверхностный рендеринг.

Пример использования mount:

import { mount } from 'enzyme';

it('работает с состоянием в mount', () => {
  const wrapper = mount(<MyComponent />);
  expect(wrapper.find('button').prop('disabled')).toBe(true);
  wrapper.setState({ isDisabled: false });
  wrapper.update();
  expect(wrapper.find('button').prop('disabled')).toBe(false);
});

Здесь компонент рендерится с полным состоянием, и проверяется, как изменяется его поведение при изменении состояния.

10. Очистка после тестов

Важно помнить, что после каждого теста состояние компонентов и глобальные объекты могут быть изменены. Для очистки используется метод afterEach, который позволяет сбрасывать все изменения между тестами.

Пример очистки:

afterEach(() => {
  jest.clearAllMocks();
});

Этот метод очищает все моки и позволяет избежать “загрязнения” тестов между различными кейсами.

11. Мокирование сторонних зависимостей

Для тестирования компонентов, использующих сторонние библиотеки или API, часто приходится мокировать их, чтобы избежать реальных запросов или изменений в окружении.

Пример мокирования библиотеки:

jest.mock('axios');
import axios from 'axios';
import MyComponent from './MyComponent';

it('обрабатывает успешный запрос', async () => {
  axios.get.mockResolvedValue({ data: 'response' });
  const wrapper = mount(<MyComponent />);
  await wrapper.instance().fetchData();
  expect(wrapper.state().data).toBe('response');
});

Здесь используется мока для библиотеки axios, что позволяет тестировать компонент без реальных запросов.

Заключение

Тестирование компонентов с помощью Enzyme включает в себя различные этапы: рендеринг, симуляция событий, проверка состояния и пропсов, а также работа с асинхронными функциями. Правильная последовательность действий и использование соответствующих методов позволяет создавать стабильные и качественные тесты для React-компонентов, обеспечивая их корректную работу на всех уровнях.