Alexander Mills
Alexander Mills

Reputation: 99960

assert.throws says => Missing expected exception

I am using this chunk of code:

       assert.throws(async () => {
            patientSubscriber = await PatientSubscriber.create({
                isSubscribed: true,
                patient: patient._id,
                subscriber: user._id
            });
        },{
             message: /foo/
        });

when I run it I get this:

AssertionError [ERR_ASSERTION]: Missing expected exception.

The assert API is: https://nodejs.org/api/assert.html#assert_assert_throws_fn_error_message

Maybe I am hitting this issue? https://github.com/nodejs/node-v0.x-archive/issues/8368

Anyone know what that error is about?

Upvotes: 5

Views: 5741

Answers (2)

myol
myol

Reputation: 9828

As commented by others, assert.rejects has been implemented since node 10.

What seems obvious with assert.rejects (but I overlooked) is that it is asynchronous, so must be awaited, otherwise the test will complete before the assertion completes.

import { rejects } from "assert";

const example = async () => { throw new Error };

await rejects(example);

If a test completes without awaiting the assert.rejects function, all tests will pass but a warning will be output. That warning can easily be missed locally or on CI.

ℹ Error: Test "testname" at test.ts:51:24 generated asynchronous activity after the test ended. This activity created the error "AssertionError [ERR_ASSERTION]: Missing expected rejection (Error)." and would have caused the test to fail, but instead triggered an unhandledRejection event.

Upvotes: 1

Estus Flask
Estus Flask

Reputation: 222309

The error means that there was no exception while it was expected. async functions are syntactic sugar for promises. They never throw exceptions but may return rejected promise.

Since the assertion is expected to be synchronous, it's impossible to assert promises this way; the entire callstack should be promise-based.

As it was mentioned in comments, assert.rejects appeared in Node 10 and results in rejected promise on assertion fail.

In case promises are handled by a caller (e.g. in most testing frameworks), rejected promise needs to be returned from current function:

it('...', async () {
  await assert.rejects((async () => {})()); // current function returns rejected promise
});

In case assertion promises aren't handled (e.g. in production), they result in UnhandledPromiseRejectionWarning console output, not in exceptions. unhandledRejection handler can be set to handle asynchronous errors:

process.on('unhandledRejection', err => {
  console.error(err);
  process.exit(1);
});

...

assert.rejects((async () => {})());

Upvotes: 16

Related Questions