Node.js assert.throws with async functions (Promises)

Since the question is still getting attention, I'd like to sum up the two best solutions, especially to highlight the new standard method.

Node v10+

There's a dedicated method in the assert library, assert.rejects.

For older versions of Node

A fill from vitalets answer:

import assert from 'assert';

async function assertThrowsAsync(fn, regExp) {
  let f = () => {};
  try {
    await fn();
  } catch(e) {
    f = () => {throw e};
  } finally {
    assert.throws(f, regExp);
  }
}

The answers given work, but I came across this issue today and came up with another solution, that I think is a little simpler.

// Code being tested
async function thisFunctionThrows() {
    throw new Error('Bad response')
}


// In your test.
try {
    await thisFunctionThrows()
    assert.equal(1 == 0) // Never gets run. But if it does you know it didn't throw.
} catch (e) {
    assert(e.message.includes('Bad response'))
}

Based on Bergi answer I've suggest more universal solution that utilizes original assert.throws for error messages:

import assert from 'assert';

async function assertThrowsAsync(fn, regExp) {
  let f = () => {};
  try {
    await fn();
  } catch(e) {
    f = () => {throw e};
  } finally {
    assert.throws(f, regExp);
  }
}

Usage:

it('should throw', async function () {
    await assertThrowsAsync(async () => await asyncTask(), /Error/);
});

node 10 and newer

Since Node.js v10.0, there is assert.rejects which does just that.

Older versions of node

async functions never throw - they return promises that might be rejected.

You cannot use assert.throws with them. You need to write your own asynchronous assertion:

async function assertThrowsAsynchronously(test, error) {
    try {
        await test();
    } catch(e) {
        if (!error || e instanceof error)
            return "everything is fine";
    }
    throw new AssertionError("Missing rejection" + (error ? " with "+error.name : ""));
}

and use it like

return assertThrowsAsynchronously(aPromise);

in an asynchronous test case.