expect(await fn()) vs await expect(fn()) for error tests with chai-as-promised
Tags: node, unittesting, javascript
Published: 2019-01-04 01:30:17

---
title: expect(await fn()) vs await expect(fn()) for error tests with chai-as-promised
published: true
canonical_url: https://www.coreycleary.me/expectawait-fn-vs-await-expectfn-for-error-tests-with-chai-as-promised/
tags: nodejs,unittesting,javascript
---
<em><strong>Originally published at <a href="https://www.coreycleary.me/expectawait-fn-vs-await-expectfn-for-error-tests-with-chai-as-promised/">coreycleary.me</a></strong>. This is a cross-post from my content blog. I publish new content every week or two, and you can <a href="https://www.coreycleary.me/about/">sign up to my newsletter</a> if you'd like to receive my articles directly to your inbox! I also regularly send cheatsheets and other freebies!</em>

<h3>The problem scenario</h3>
Ah, writing tests for errors. It's fun, isn't it? Have you ever written a unit test expecting to catch an error with Chai, and gotten something like the below?

<blockquote>I don't understand why `expect(await fn()).to.be.rejectedWith(`I'm an error!`)` is failing... we're calling the function, getting an error, and asserting on that... why isn't it passing?</blockquote>
<img src="https://www.coreycleary.me/wp-content/uploads/2018/12/Screen-Shot-2018-12-30-at-1.42.33-PM.png" alt="" width="329" height="120" class="aligncenter size-full wp-image-874" />

Writing tests can often fall to the wayside, and when you have a failing test that's driving you crazy, you're probably more likely to just strip out the test.

We want testing to be easy and somewhat enjoyable. If it's not, then something's wrong.

I've covered a bit about <a href="https://www.coreycleary.me/why-isnt-this-unit-test-catching-an-error-from-this-async-await-function/" rel="noopener" target="_blank">how to write tests for errors from Promises/async functions before</a>, but now let's take a deeper look into <strong>why</strong> doing `expect(await fn())` won't work when you're expecting an error/rejected promise.

<h3>What we're really doing when we write `expect(await fn()).to.be.rejectedWith(error)`</h3>
Suppose the function we're testing is the one below:
```javascript
const someFn = async () => {
  throw new Error(`I'm an error!`)
}
```
And here's our test setup using Chai / chai-as-promised:
```javascript
const chai = require('chai')
const chaiAsPromised = require('chai-as-promised')

const { someFn, otherFn } = require('./index')

const expect = chai.expect
chai.use(chaiAsPromised)
```
<em>We're purposefully throwing an error / rejecting the Promise for purposes on demonstrating testing for errors.</em>
In our test, when we do this:
```javascript
expect(await fn()).to.be.rejectedWith(`I'm an error!`)
```
It is the same thing as doing this:
```javascript
const res = await someFn()
expect(res).to.be.rejectedWith(`I'm an error!`)
```
Pulling the `await someFn()` result out into a variable helps make this clearer as to what's going on.

As we are not catching the result of the function, we don't catch the error. The error just ends up being printed to the console, and the test fails.<img src="https://www.coreycleary.me/wp-content/uploads/2018/12/Screen-Shot-2018-12-30-at-1.42.33-PM.png" alt="" width="329" height="120" class="aligncenter size-full wp-image-874" />
<em>Side note: normally we should expect an UnhandledPromiseRejection to show up in the console as well, but Mocha has some in-built error handling / promise rejection handling that is catching this instead.</em>

<h3>What we should be doing instead</h3>
Instead, what we should do to test for our error / rejected promise is this:
```javascript
await expect(someFn()).to.be.rejectedWith(`I'm an error!`)
```
When we put the `await` in front of the `expect`, Chai / chai-as-promised is able to check for the rejected promise. We `await` on the assertion, and this allows us to catch and check the error.

<h3>Wrapping up</h3>
It's quirky things like this that can derail you in the JavaScript/Node world. And like I mentioned earlier, if tests are cumbersome to write, more often than not they just don't get written.

I have plenty more testing content planned for the future, so if you found this helpful and want to receive it directly to your inbox without having to remember to check back here, <a href="https://www.coreycleary.me/expectawait-fn-vs-await-expectfn-for-error-tests-with-chai-as-promised/">sign up to the mailing list here!</a>