使用 Mocha / Chai 和 async/await 验证是否引发了异常

新手上路,请多包涵

我正在努力寻找在使用 async/await 时验证承诺在 Mocha 测试中被拒绝的最佳方法。

这是一个有效的示例,但我不喜欢 should.be.rejectedWith 返回一个需要从测试函数返回才能正确评估的承诺。使用 async/await 消除了对测试值的这一要求(就像我对下面 wins() 的结果所做的那样),我觉得我可能会在某些时候忘记 return 语句,在这种情况下测试总会通过。

 // Always succeeds
function wins() {
  return new Promise(function(resolve, reject) {
    resolve('Winner');
  });
}

// Always fails with an error
function fails() {
  return new Promise(function(resolve, reject) {
    reject('Contrived Error');
  });
}

it('throws an error', async () => {
  let r = await wins();
  r.should.equal('Winner');

  return fails().should.be.rejectedWith('Contrived Error');
});

感觉应该可以使用 async/await 将拒绝转换为异常并将其与 Chai 的 should.throw 相结合的事实,但我无法确定正确的语法。

理想情况下,这会起作用,但似乎不起作用:

 it('throws an error', async () => {
  let r = await wins();
  r.should.equal('Winner');

  (await fails()).should.throw(Error);
});

原文由 plexer 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 525
1 个回答

这种方法的问题是 (await fails()).should.throw(Error) 没有意义。

await 解析为 Promise 。如果 Promise 拒绝,它会抛出被拒绝的值。

所以 (await fails()).should.throw(Error) 永远无法工作:如果 fails() 拒绝,则会抛出错误,并且 .should.throw(Error) 永远不会执行。

您拥有的最惯用的选择是使用 Chai 的 rejectedWith 属性,如您在问题中所示。

这是一个简单的例子。与您在问题中展示的内容没有太大区别; I’m just using async functions for wins() and fails() and expect instead of should .当然,您可以使用返回 Promisechai.should 的函数就好了。

 const chai = require('chai')
const expect = chai.expect
chai.use(require('chai-as-promised'))

// Always succeeds
async function wins() {
  return 'Winner'
}

// Always fails with an error
async function fails() {
  throw new Error('Contrived Error')
}

it('wins() returns Winner', async () => {
  expect(await wins()).to.equal('Winner')
})

it('fails() throws Error', async () => {
  await expect(fails()).to.be.rejectedWith(Error)
})

如果你喜欢你的 wins() 测试类似于你的 fails() 测试更仔细,你可以写你的 wins() 测试像这样:

 it('wins() returns Winner', async () => {
  await expect(wins()).to.eventually.equal('Winner')
})

在这两个示例中,要记住的关键是 chai-as-promised 为其函数返回承诺,例如 rejectedWitheventually.something 。因此,您必须 await 它们在 async 测试函数的上下文中,否则失败的条件仍然会通过:

 async function wins() {
  return 'Loser'
}

async function fails() {
  return 'Winner'
}

it('wins() returns Winner', async () => {
  expect(wins()).to.eventually.equal('Winner')
})

it('fails() throws Error', async () => {
  expect(fails()).to.be.rejectedWith(Error)
})

如果您使用上面的代码运行测试,您将得到以下结果:

 $ npm test

> mocha-chai-async@1.0.0 test /home/adaline/code/mocha-chai-async
> mocha .

  √ wins() returns Winner
(node:13836) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rej
ection id: 1): AssertionError: expected 'Loser' to equal 'Winner'
(node:13836) [DEP0018] DeprecationWarning: Unhandled promise rejections are dep
recated. In the future, promise rejections that are not handled will terminate
the Node.js process with a non-zero exit code.
  √ fails() throws Error
(node:13836) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rej
ection id: 2): AssertionError: expected promise to be rejected with 'Error' but
 it was fulfilled with 'Winner'

  2 passing (11ms)

如您所见,chai 断言实际上失败了,但它们在 Promise 的上下文中失败了,该 Promise 从未有人 await 编辑或 catch 编辑。所以 Mocha 看不到失败并将测试标记为通过,但是 Node.js(如上所述,在未来会改变的行为中)将未处理的拒绝打印到终端。

原文由 Adaline Simonian 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题