验证是否使用Mocha/Chai和async/await引发了异常 [英] Verify that an exception is thrown using Mocha / Chai and async/await

查看:471
本文介绍了验证是否使用Mocha/Chai和async/await引发了异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力找到一种最佳方法,以验证使用async/await时在Mocha测试中否定了诺言.

I'm struggling to work out the best way to verify that a promise is rejected in a Mocha test while using async/await.

这是一个可行的示例,但我不喜欢should.be.rejectedWith返回一个必须从测试函数中返回才能进行正确评估的promise.使用async/await消除了测试值的要求(就像我对下面的wins()的结果所做的那样),并且我觉得我有时可能会忘记return语句,在这种情况下,测试将始终通过

Here's an example that works, but I dislike that should.be.rejectedWith returns a promise that needs to be returned from the test function to be evaluated properly. Using async/await removes this requirement for testing values (as I do for the result of wins() below), and I feel that it is likely that I will forget the return statement at some point, in which case the test will always pass.

// 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 feels like it should be possible to use the fact that async/await translates rejections to exceptions and combine that with Chai's should.throw, but I haven't been able to determine the correct syntax.

理想情况下,这是可行的,但似乎不可行:

Ideally this would work, but does not seem to:

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

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

推荐答案

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

The problem with this approach is that (await fails()).should.throw(Error) doesn't make sense.

await解析Promise.如果Promise拒绝,则会抛出拒绝的值.

await resolves a Promise. If the Promise rejects, it throws the rejected value.

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

So (await fails()).should.throw(Error) can never work: if fails() rejects, an error is thrown, and .should.throw(Error) is never executed.

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

The most idiomatic option you have is to use Chai's rejectedWith property, as you have shown in your question.

这是一个简单的例子.与您在问题中所展示的内容没有太大不同;我只是将async函数用于wins()fails()expect而不是should.当然,您可以使用返回Promisechai.should的函数.

Here's a quick example. Not much is different from what you've demonstrated in your question; I'm just using async functions for wins() and fails() and expect instead of should. Of course, you can use functions that return a Promise and chai.should just fine.

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()测试:

If you like want your wins() test to resemble your fails() test more closely, you can write your wins() test like so:

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

在这两个示例中,要记住的关键是chai-as-promised返回其功能(例如rejectedWitheventually.something)的promise.因此,必须在async测试功能的上下文中await它们,否则失败的条件仍会通过:

The key thing to remember in either of these examples is that chai-as-promised returns promises for its functions such as rejectedWith and eventually.something. Therefore you must await them in the context of an async test function, or else failing conditions will still pass:

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)
})

如果使用上面的代码运行测试,则会得到以下内容:

If you ran the tests with the code above, you'd get the following:

$ npm test

> mocha-chai-async@1.0.0 test /home/vsimonian/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断言实际上失败了,但是在没有人进行过awaitcatch的Promise的背景下,它们失败了.因此,Mocha不会看到任何失败,并且将测试标记为好像已通过,但是Node.js(行为将如上所述发生变化,如上所述)将未处理的拒绝打印到终端.

As you can see, the chai assertions actually failed, but they were failed in the context of a Promise that no one ever awaited or catched. So Mocha sees no failure and marks the tests as though they passed, but Node.js (in behaviour that will change in the future as noted above) prints the unhandled rejections to the terminal.

这篇关于验证是否使用Mocha/Chai和async/await引发了异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆