docs/api/assert/rejects.md
rejects( promise, message = "" )
rejects( promise, expectedMatcher, message = "" )
Test if the provided promise rejects, and optionally compare the rejection value.
| name | description |
|---|---|
promise (thenable) | Promise to test for rejection |
expectedMatcher | Rejection value matcher |
message (string) | Short description of the assertion |
When testing code that is expected to return a rejected promise based on a
specific set of circumstances, use assert.rejects() for testing and
comparison.
The expectedMatcher argument can be:
true when the assertion should be considered passing.rejectionValue instanceof expectedMatcher.rejectionValue.toString().Note: in order to avoid confusion between the message and the expectedMatcher, the expectedMatcher can not be a string.
assert.throws() for synchronous errors.async function feedBaby (food) {
if (food === 'sprouts') {
throw new RangeError('Do not like');
}
return true;
}
QUnit.test('example', async function (assert) {
assert.true(feedBaby('apple'));
await assert.rejects(feedBaby('sprouts'), RangeError);
assert.true(feedBaby('cucumber'), RangeError);
});
QUnit.test('rejects example', function (assert) {
// simple check
assert.rejects(Promise.reject('some error'));
// simple check
assert.rejects(
Promise.reject('some error'),
'optional description here'
);
// match pattern on actual error
assert.rejects(
Promise.reject(new Error('some error')),
/some error/,
'optional description here'
);
// Using a custom error constructor
function CustomError (message) {
this.message = message;
}
CustomError.prototype.toString = function () {
return this.message;
};
// actual error is an instance of the expected constructor
assert.rejects(
Promise.reject(new CustomError('some error')),
CustomError
);
// actual error has strictly equal `constructor`, `name` and `message` properties
// of the expected error object
assert.rejects(
Promise.reject(new CustomError('some error')),
new CustomError('some error')
);
// custom validation arrow function
assert.rejects(
Promise.reject(new CustomError('some error')),
(err) => err.toString() === 'some error'
);
// custom validation function
assert.rejects(
Promise.reject(new CustomError('some error')),
function (err) {
return err.toString() === 'some error';
}
);
});
When you pass a Promise (or async function call) to assert.rejects(), QUnit automatically tracks this as part of your test. This tracking is similar to what would happen if you manually passed assert.async() to promise.finally(). This means the test is not complete until the passed Promise is also settled, and this means timeouts naturally apply as well.
However, if two parts of your test code or subject share state within a single test, you may want to await the assertion to prevent the rest of your test from running at the same time.
To make this easy, the assert.rejects() method itself can be awaited, which will wait for the given async function call or other Promise.
QUnit.test('stateful example', async function (assert) {
let value;
async function feedMe () {
await Promise.resolve();
if (value === 1) {
throw new Error('I want more');
}
throw new Error('Thank you');
}
value = 5;
// if we don't await, then this test will fail,
// because `value = 1` would run too soon.
await assert.rejects(feedMe(), /Thank you/);
value = 1;
await assert.rejects(feedMe(), /I want more/);
});
Avoid using error handling callbacks, such as Promise.catch or on('error'), because:
QUnit.test('BAD example', function (assert) {
return feedBaby('sprouts')
.catch((e) => {
assert.true(e instanceof RangeError);
});
});
Avoid manually tracking rejections with assert.async(), because:
QUnit.test('BAD example', function (assert) {
const done = assert.async();
feedBaby('sprouts')
.then(() => {
assert.true(false, 'should have failed');
})
.catch((e) => {
assert.true(e instanceof RangeError);
})
.finally(done);
});
If you want to perform additional assertions after a failure, consider performing these directly in your test function, after assert.rejects():
QUnit.test('example', async function (assert) {
const p = feedMe();
await assert.rejects(p, RangeError);
try {
await p;
} catch (e) {
assert.deepEqual(e.somedata, { foo: 'bar' });
}
});