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

Я работаю с некоторым кодом, где мне нужно проверить тип исключения, созданного функцией (это TypeError, ReferenceError и т.д.).

Моя текущая структура тестирования - AVA, и я могу проверить ее как второй аргумент метода t.throws, например здесь:

it('should throw Error with message \'UNKNOWN ERROR\' when no params were passed', (t) => {
  const error = t.throws(() => {
    throwError();
  }, TypeError);

  t.is(error.message, 'UNKNOWN ERROR');
});

Я начал переписывать свои тесты на Jest и не мог найти, как легко это сделать. Возможно ли это?

Ответы

Ответ 1

В Jest вам нужно передать функцию в функцию ожидания (function).toThrow (пустое или тип ошибки).

Пример:

test("Test description", () => {
  const t = () => {
    throw new TypeError();
  };
  expect(t).toThrow(TypeError);
});

Если вам нужно проверить существующую функцию, выбрасывает ли она с помощью набора аргументов, вы должны обернуть ее внутри анонимной функции в expect().

Пример:

test("Test description", () => {
  expect(() => {http.get(yourUrl, yourCallbackFn)}).toThrow(TypeError);
});

Ответ 2

Немного странно, но работает, и imho хорошо читается:

it('should throw Error with message \'UNKNOWN ERROR\' when no params were passed', () => {
  try {
      throwError();
      // Fail test if above expression does not throw anything.
      expect(true).toBe(false);
  } catch (e) {
      expect(e.message).toBe("UNKNOWN ERROR");
  }
});

Блок Catch перехватывает ваше исключение, затем вы можете проверить на поднятом Error. Странный expect(true).toBe(false); необходим, чтобы провалить ваш тест, если ожидаемый Error не будет брошен. В противном случае эта строка никогда не будет достигнута (перед ними следует Error).

ОБНОВЛЕНИЕ: @Kenny Body предлагает лучшее решение, которое улучшит качество кода, если вы используете expect.assertions()

it('should throw Error with message \'UNKNOWN ERROR\' when no params were passed', () => {
  expect.assertions(1);
  try {
      throwError();
  } catch (e) {
      expect(e.message).toBe("UNKNOWN ERROR");
  }
});

См. оригинальный ответ с дополнительными пояснениями: Как проверить тип сгенерированного исключения в Jest?

Ответ 3

Я использую немного более краткую версию:

expect(() => {
  //code block that should throw error
}).toThrow(TypeError) //or .toThrow('expectedErrorMessage')

Ответ 4

Сам не пробовал, но я бы предложил использовать утверждение Jest toThrow. Итак, я думаю, ваш пример будет выглядеть примерно так:

it('should throw Error with message \'UNKNOWN ERROR\' when no params were passed', (t) => {
  const error = t.throws(() => {
    throwError();
  }, TypeError);

  expect(t).toThrowError('UNKNOWN ERROR');
  //or
  expect(t).toThrowError(TypeError);
});

Опять же, не проверял, но я думаю, что это должно работать.

Дайте мне знать, если это помогло.

Удачного кодирования!

Ответ 5

В Jest есть метод toThrow(error) для проверки того, что функция выдает при вызове.

Итак, в вашем случае вы должны назвать это так:

expect(t).toThrowError(TypeError);

Документы

Ответ 6

Из моего (хотя и ограниченного) контакта с Jest я обнаружил, что expect().toThrow() подходит, если вы хотите ТОЛЬКО проверить, выдана ли ошибка с конкретным сообщением:

expect(() => functionUnderTest()).toThrow(TypeError);

ИЛИ выдается ошибка определенного типа:

expect(() => functionUnderTest()).toThrow('Something bad happened!');

Если вы попытаетесь сделать оба, вы получите ложный положительный результат. Например, если ваш код выдает RangeError('Something bad happened!'), этот тест пройдет:

expect(() => functionUnderTest()).toThrow(new TypeError('Something bad happened!'));

Ответ от bodolsog, который предлагает использовать попытку/улов, близок, но вместо того, чтобы ожидать, что истина будет ложной, чтобы гарантировать, что ожидаемые утверждения в улове достигнуты, вы можете вместо этого использовать expect.assertions(2) в начале теста, где 2 количество ожидаемых утверждений. Я чувствую, что это более точно описывает цель теста.

Полный пример тестирования сообщения типа И об ошибке:

describe('functionUnderTest', () => {
    it('should throw a specific type of error.', () => {
        expect.assertions(2);

        try {
            functionUnderTest();
        } catch (error) {
            expect(error).toBeInstanceOf(TypeError);
            expect(error).toHaveProperty('message', 'Something bad happened!');
        }
    }); 
});

Если functionUnderTest() НЕ выдает ошибку, утверждения будут сброшены, но expect.assertions(2) потерпит неудачу и тест не пройдёт.

Ответ 7

пытаться
expect(t).rejects.toThrow()

Ответ 8

В итоге я написал удобный метод для нашей библиотеки test-utils

/**
 *  Utility method to test for a specific error class and message in Jest
 * @param {fn, expectedErrorClass, expectedErrorMessage }
 * @example   failTest({
      fn: () => {
        return new MyObject({
          param: 'stuff'
        })
      },
      expectedErrorClass: MyError,
      expectedErrorMessage: 'stuff not yet implemented'
    })
 */
  failTest: ({ fn, expectedErrorClass, expectedErrorMessage }) => {
    try {
      fn()
      expect(true).toBeFalsy()
    } catch (err) {
      let isExpectedErr = err instanceof expectedErrorClass
      expect(isExpectedErr).toBeTruthy()
      expect(err.message).toBe(expectedErrorMessage)
    }
  }

Ответ 9

Современный шут позволяет больше проверять отклоненную стоимость. Например:

const request = Promise.reject({statusCode: 404})
await expect(request).rejects.toMatchObject({ statusCode: 500 });

завершится ошибкой

Error: expect(received).rejects.toMatchObject(expected)

- Expected
+ Received

  Object {
-   "statusCode": 500,
+   "statusCode": 404,
  }