4.1 Testing Error throws

In library or shared code, throwing errors can be useful to enforce an interface for a function for example.

This code should be tested, which can be challenging and differs based on the type of code under test.

This section tackles detection of throw-ing a JavaScript error in a synchronous and an asynchronous context.

Check a synchronous function throws using the .toThrow Jest matcher

Given a function that doesn’t throw like noError as follows.

function noError() {
  return 'success';
}

We can write a test asserting it doesn’t throw using expect().not.toThrow()

test('should not throw', () => {
  expect(throws.bind(null)).not.toThrow(
    new Error('throwing')
  );
});

The test passes since the code under test doesn’t throw, but this time we get a Received function did not throw error, which is maybe more descriptive and shows the advantage of using the Jest .toThrow matcher.

npx jest src/04.01-no-throw.test.js
 PASS  src/04.01-no-throw.test.js
  ✓ should throw if passed true (3ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total

Say we have a function that throws:

function throws() {
  throw new Error('throwing')
}

We can check that it throws with expect().toThrow(error).

test('should throw if passed true', () => {
  expect(throws.bind(null)).toThrow(
    new Error('throwing')
  );
});

This test is passing since the function throws as we have asserted.

npx jest src/04.01-throws.test.js
 PASS  src/04.01-throws.test.js
  ✓ should throw if passed true (5ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total

Check an async function throws using expect().rejects.toEqual

The idiomatic Jest way to check an async function throws is to use the await or return an expect(fn(param1)).rejects.toEqual(error).

Note: make sure to await or return the expect() expression, otherwise Jest might not see the error as a failure but an UnHandledPromiseRejection

async function asyncThrowOrNot() {
  throw new Error('async-throw')
}
test('should throw return expect()', async () => {
  return expect(asyncThrowOrNot()).rejects.toEqual(
    new Error('async-throw')
  );
});

test('should throw await expect()', async () => {
  await expect(asyncThrowOrNot()).rejects.toEqual(
    new Error('async-throw')
  );
});

These tests pass on async throw's as expected, as per the following output.

npx jest src/04.01-async-throw.test.js
 PASS  src/04.01-async-throw.test.js
  ✓ should throw return expect() (3ms)
  ✓ should throw await expect() (1ms)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total

This section showed how one might test test that’s designed to throw, both in the synchronous and the asynchronous case.

The next section tackles mocking the output of stubbed sync and async functions with Jest.

Jump to table of contents