Матчеры для исключений

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

Проверка выброса исключений с помощью toThrow

Метод toThrow — это основной матчере Jest для проверки выброса исключений. Этот матчере проверяет, что функция выбрасывает ошибку при её вызове.

test('Функция выбрасывает исключение', () => {
  const fn = () => {
    throw new Error('Что-то пошло не так');
  };

  expect(fn).toThrow();
});

В примере выше проверяется, что при вызове функции fn выбрасывается ошибка. Если исключение не выбрасывается, тест завершится с ошибкой. Однако, часто полезно проверять не только факт выброса исключения, но и тип или сообщение ошибки.

Проверка конкретного типа исключения

Для того чтобы убедиться, что выбрасывается ошибка определённого типа, можно передать в toThrow регулярное выражение или строку. Если передано регулярное выражение, оно будет проверять сообщение ошибки на соответствие.

test('Ошибка выбрасывается с правильным сообщением', () => {
  const fn = () => {
    throw new Error('Не удаётся выполнить операцию');
  };

  expect(fn).toThrow('Не удаётся выполнить операцию');
});

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

test('Ошибка выбрасывается с правильным типом и сообщением', () => {
  const fn = () => {
    throw new TypeError('Некорректный тип данных');
  };

  expect(fn).toThrow(TypeError);
  expect(fn).toThrow('Некорректный тип данных');
});

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

Проверка асинхронных ошибок с помощью async и await

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

1. Проверка с использованием async/await:

Если функция возвращает промис, который может выбросить исключение, его можно обрабатывать с помощью async/await:

test('Асинхронная функция выбрасывает исключение', async () => {
  const asyncFn = async () => {
    throw new Error('Ошибка асинхронной функции');
  };

  await expect(asyncFn()).rejects.toThrow('Ошибка асинхронной функции');
});

Здесь проверяется, что асинхронная функция asyncFn выбрасывает ошибку с ожидаемым сообщением.

2. Проверка с использованием resolves/rejects:

Jest также предоставляет более специализированные матчеры resolves и rejects для работы с асинхронными функциями:

test('Асинхронная функция выбрасывает ошибку с reject', async () => {
  const asyncFn = async () => {
    return Promise.reject(new Error('Ошибка при асинхронной операции'));
  };

  await expect(asyncFn()).rejects.toThrow('Ошибка при асинхронной операции');
});

Здесь матчере rejects используется для проверки, что промис, возвращённый асинхронной функцией, отклоняется с ожидаемой ошибкой.

Проверка ошибок с помощью toThrowError

Метод toThrowError является более специализированной версией toThrow. Он позволяет проверять, что исключение является объектом ошибки (Error), а не просто строкой или другим типом данных.

test('Проверка на объект ошибки', () => {
  const fn = () => {
    throw new Error('Ошибка с объектом');
  };

  expect(fn).toThrowError(Error);
  expect(fn).toThrowError('Ошибка с объектом');
});

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

Дополнительные возможности: матчеры для проверки ошибок с объектами

Для более детальной проверки содержимого ошибки, например, её свойств или кодов состояния, можно использовать сочетание toThrowError с методами toHaveProperty или toMatchObject.

test('Проверка объекта ошибки с дополнительными свойствами', () => {
  const fn = () => {
    const error = new Error('Некорректный запрос');
    error.statusCode = 400;
    throw error;
  };

  const errorMatcher = expect(fn).toThrowError();
  errorMatcher.then(error => {
    expect(error).toHaveProperty('statusCode', 400);
  });
});

Этот пример показывает, как можно проверить не только текст ошибки, но и дополнительные свойства объекта ошибки, такие как statusCode.

Подведение итогов

Матчеры для исключений в Jest являются важным инструментом для тестирования правильности обработки ошибок. С их помощью можно не только проверить факт выброса ошибки, но и убедиться в её типе и содержимом. Важно правильно выбирать матчеры в зависимости от специфики тестируемого кода: для синхронных функций удобно использовать toThrow, для асинхронных — rejects и resolves, а для более детальных проверок ошибок — toThrowError и дополнительные методы для проверки свойств объекта ошибки.