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


当前回答

我设法把一些答案结合起来,最后得到了这样的答案:

it('should throw', async () => {
    await expect(service.methodName('some@email.com', 'unknown')).rejects.toThrow(
      HttpException,
    );
  });

其他回答

我用了一个稍微简洁一点的版本:

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

我已经成功地使用了这个方法

await expect(
      async () => await apiCalls()
    ).rejects.toThrow();

这有点奇怪,但它是有效的,以我之见是很好的可读性:

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

Catch块捕获您的异常,然后您可以测试您引发的Error。奇怪的期待(真正的).toBe(假);如果没有抛出预期的错误,则需要测试失败。否则,这一行永远无法到达(Error应该在它们之前引发)。

@Kenny Body提出了一个更好的解决方案,如果你使用expect.assertions(),可以提高代码质量:

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

请参阅原始答案和更多解释:如何在Jest中测试抛出异常的类型

2022年编辑:

要使用这种方法而不触发no-conditional-expect规则(如果你使用eslint-plugin-jest),该规则的文档建议使用错误包装器:

class NoErrorThrownError extends Error {}

const getError = async <TError>(call: () => unknown): Promise<TError> => {
  try {
    await call();

    throw new NoErrorThrownError();
  } catch (error: unknown) {
    return error as TError;
  }
};

describe('when the http request fails', () => {
  it('includes the status code in the error', async () => {
    const error = await getError(async () => makeRequest(url));

    // check that the returned error wasn't that no error was thrown
    expect(error).not.toBeInstanceOf(NoErrorThrownError);
    expect(error).toHaveProperty('statusCode', 404);
  });
});

参见:no-conditional-expect文档

我自己没有尝试过,但我建议使用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);
});

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

您必须将期望的函数代码包装在另一个箭头函数中,否则错误将不会被捕获,断言将失败。

要测试的函数:

const testThrowingError = () => {
    throw new Error();
  };

测试:

describe("error function should Throw Error", () => {
  expect(() =>testThrowingError()).toThrowError();
});

资源: https://jestjs.io/docs/expect#tothrowerror