Тестирование обработчиков ошибок

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

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

Структура тестов с обработчиками ошибок

Чтобы корректно протестировать обработчики ошибок, важно разделить тесты на несколько категорий:

  1. Тесты на наличие ошибок — проверка того, что в случае возникновения ошибки компонент реагирует, как ожидается.
  2. Тесты на поведение компонента после возникновения ошибки — проверка, что компонент ведет себя должным образом после обработки ошибки (например, показ сообщения об ошибке или переход к альтернативному состоянию).
  3. Тесты на корректность данных — проверка того, что данные, связанные с ошибкой, правильно передаются и отображаются.

Пример тестирования обработчика ошибок

Рассмотрим пример компонента, который выполняет асинхронный запрос и обрабатывает ошибки. Компонент должен отображать сообщение об ошибке, если запрос не удался.

import React, { useState, useEffect } from 'react';

function DataFetcher() {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetchData();
  }, []);

  const fetchData = async () => {
    try {
      const response = await fetch('https://example.com/data');
      if (!response.ok) {
        throw new Error('Network response was not ok');
      }
      const result = await response.json();
      setData(result);
    } catch (error) {
      setError(error.message);
    }
  };

  if (error) {
    return <div className="error">{error}</div>;
  }

  if (!data) {
    return <div>Loading...</div>;
  }

  return <div>{data}</div>;
}

export default DataFetcher;

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

Теперь создадим тесты для проверки обработки ошибок с использованием Enzyme.

Написание тестов с Enzyme

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

  1. Инициализация теста и мокирование fetch Для тестирования компонента, который выполняет асинхронные операции, таких как HTTP-запросы, важно мокировать эти операции, чтобы не зависеть от реальных данных или сети. В Jest это можно сделать с помощью jest.mock.
import { shallow } from 'enzyme';
import DataFetcher from './DataFetcher';

jest.mock('global', () => ({
  ...global,
  fetch: jest.fn(),
}));

describe('<DataFetcher />', () => {
  it('должен отображать сообщение об ошибке при неудачном запросе', async () => {
    fetch.mockImplementationOnce(() => Promise.reject(new Error('Ошибка сети')));

    const wrapper = shallow(<DataFetcher />);
    await wrapper.instance().componentDidMount();
    wrapper.update();
    
    expect(wrapper.containsMatchingElement(<div className="error">Ошибка сети</div>)).toBe(true);
  });
});

В этом тесте мы мокируем функцию fetch, чтобы она всегда возвращала ошибку. После того как компонент загрузится, мы проверяем, что на экране появится элемент с сообщением об ошибке.

  1. Тестирование успешного запроса Кроме проверки ошибок, важно также тестировать успешные сценарии, когда запрос проходит корректно и данные загружаются.
it('должен отображать данные после успешного запроса', async () => {
  const mockData = { name: 'Test Data' };
  fetch.mockImplementationOnce(() => Promise.resolve({ ok: true, json: () => Promise.resolve(mockData) }));

  const wrapper = shallow(<DataFetcher />);
  await wrapper.instance().componentDidMount();
  wrapper.update();

  expect(wrapper.containsMatchingElement(<div>{mockData.name}</div>)).toBe(true);
});

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

Тестирование скрытых ошибок

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

Можно использовать jest.spyOn для проверки того, что функция записи ошибки была вызвана.

it('должен вызывать console.error при ошибке', async () => {
  const spy = jest.spyOn(console, 'error').mockImplementation(() => {});
  fetch.mockImplementationOnce(() => Promise.reject(new Error('Ошибка сети')));

  const wrapper = shallow(<DataFetcher />);
  await wrapper.instance().componentDidMount();

  expect(spy).toHaveBeenCalledWith('Ошибка сети');
  spy.mockRestore();
});

Здесь мы проверяем, что при ошибке в запросе будет вызвано логирование ошибки через console.error. Это важный момент для тестирования скрытых механизмов обработки ошибок.

Тестирование отображения различных состояний

Компоненты часто переходят между различными состояниями в зависимости от результата запроса: сначала отображают «Загрузка», затем либо данные, либо сообщение об ошибке. Важно проверить эти переходы.

it('должен отображать "Загрузка", пока не получены данные', () => {
  const wrapper = shallow(<DataFetcher />);
  expect(wrapper.containsMatchingElement(<div>Loading...</div>)).toBe(true);
});

Этот тест проверяет, что компонент правильно отображает текст «Загрузка», пока данные не получены.

Заключение

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