我正在使用一些代码,其中我需要测试由函数抛出的异常的类型(它是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重写我的测试,但不知道如何轻松地做到这一点。这可能吗?


当前回答

还有一种更简单的方法对错误消息进行断言。这种方法的美妙之处在于,您不需要重新构造错误对象或获得完整的错误消息。只要您的错误包含错误消息的一部分,我们就可以假设它的类型是正确的。即

 const printOnlyString = (str) => {
   if(typeof str !== "string"){
     throw Error("I can only print strings ${typeof str) given");
   }
   else {
     console.log(str);
   } 
 }

expect(() => printOnlyString(123))。toThrow(/只能打印字符串/)

其他回答

我自己没有尝试过,但我建议使用Jest的toThrow断言。所以我猜你的例子应该是这样的:

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

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

同样,我还没有测试它,但我认为它应该可以工作。

如果你正在使用Promises:

await expect(Promise.reject(new HttpException('Error message', 402)))
  .rejects.toThrowError(HttpException);

文档清楚地说明了如何做到这一点。假设我有一个函数,它有两个参数,如果其中一个为空,它就会抛出一个错误。

function concatStr(str1, str2) {
  const isStr1 = str1 === null
  const isStr2 = str2 === null
  if(isStr1 || isStr2) {
    throw "Parameters can't be null"
  }
  ... // Continue your code

您的测试

describe("errors", () => {
  it("should error if any is null", () => {
    // Notice that the expect has a function that returns the function under test
    expect(() => concatStr(null, "test")).toThrow()
  })
})

从我对Jest的接触(尽管有限)中,我发现expect().toThrow()适用于只想测试抛出的特定类型的错误:

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

或者抛出一个带有特定消息的错误:

expect(() => functionUnderTest())。toThrow('发生了不好的事情!');

如果你试图同时做这两件事,你会得到一个假阳性。例如,如果你的代码抛出RangeError('坏事发生了!'),这个测试将通过:

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

bodolsog给出的答案很接近,它建议使用try/catch,但与其期望true为false以确保捕获中的expect断言被命中,不如在测试开始时使用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)将失败,测试也将失败。

还有一种更简单的方法对错误消息进行断言。这种方法的美妙之处在于,您不需要重新构造错误对象或获得完整的错误消息。只要您的错误包含错误消息的一部分,我们就可以假设它的类型是正确的。即

 const printOnlyString = (str) => {
   if(typeof str !== "string"){
     throw Error("I can only print strings ${typeof str) given");
   }
   else {
     console.log(str);
   } 
 }

expect(() => printOnlyString(123))。toThrow(/只能打印字符串/)