测试异步函数以使用 mocha 抛出

Test async function to throw with mocha

我有一个运行 2000 毫秒的异步函数,然后它会抛出异常。我正在尝试使用 Mocha / chai 来准确测试这种行为,但显然我做错了。

这是我试过的:

第一个:

expect(publisher.dispatchMessage<ExampleResponseMessage>(message, {}, 2 * 1000)).to.eventually.throw();

这将测试标记为已通过(52 毫秒运行时间),但在 2 秒后抛出异常。所以显然它根本没有等待该功能的承诺。

第二个:

expect(async () => {
      await publisher.dispatchMessage<ExampleResponseMessage>(message, {}, 2 * 1000);
    }).to.throw();

测试失败: 应该在预定义的超时后拒绝预定的消息: AssertionError:预期 [Function] 抛出错误 在 Context.mocha_1.it (test\integration\rpc-communication.spec.ts:75:16) 在

预期的行为是测试通过,因为在 2000 毫秒后抛出异常,这在给定的测试用例超时 4000 毫秒内。

附加信息:

这行得通。承诺因错误而被拒绝(我也可以将其更改为使用字符串拒绝)。这应该证明 dispatchMessage() 正在按预期工作。测试用例耗时2002ms然后通过

    try {
      await publisher.dispatchMessage<ExampleResponseMessage>(message, {}, 2 * 1000);
    } catch (err) {
      expect(err).to.be.an('Error');
    }

问题:

如何正确测试异步函数是否抛出异常?

.to.throw() 不应该在 async 函数上工作,因为它不会抛出错误,它 returns 拒绝了承诺。

问题是 chai-as-promised 特有的。如 this issue 中所述,.to.eventually.throw() 将无法按预期工作。它断言一个 promise resolves 的函数会在调用时同步 throw 错误。这可能不是 dispatchMessage.

中发生的情况

这取决于 dispatchMessage 但可能应该是:

expect(publisher.dispatchMessage<ExampleResponseMessage>(message, {}, 2 * 1000))
.to.be.rejected;

Chai 支持 async/await 测试功能。要断言承诺拒绝,您可以使用 rejectedrejectedWith 来自 chai-as-promise 插件。

因为 rejected return 一个承诺,你需要一个 await 否则测试用例会在承诺被拒绝之前完成。

it('should be rejected', async () => {
  await expect(
    publisher.dispatchMessage<ExampleResponseMessage>(message, {}, 2 * 1000)
  ).to.be.rejected;
}

其他答案对我不起作用(也许我没有正确的 Chai 版本?),所以我是这样解决的。

首先,定义这个实用函数:

const shouldReject = async (promise:Promise<any>, errorClass?:Function|Error, message?:string):Promise<void> => {
  let error = null;
  try {
    await promise;
  }
  catch (e) {
    error = e;
  }
  expect(error).to.not.be.null;
  if(errorClass !== undefined)
    error.should.be.an.instanceOf(errorClass);
  if(message !== undefined)
    error.message.should.equal(message);
};

在您的示例中,您可以像这样使用它:

it('should be rejected', async () => {
  await shouldReject(
    publisher.dispatchMessage<ExampleResponseMessage>(message, {}, 2 * 1000)
  );
}