assert: support custom errors

This commit adds special handling of Error instances when passed
as the message argument to assert functions. With this commit,
if an Error is passed as the message, then that Error is thrown
instead of an AssertionError.

PR-URL: https://github.com/nodejs/node/pull/15304
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
This commit is contained in:
geek 2017-09-09 20:36:47 -05:00 committed by cjihrig
parent a10856a7d3
commit e13d1df89b
No known key found for this signature in database
GPG Key ID: 7434390BDBE9B9C5
4 changed files with 93 additions and 18 deletions

View File

@ -101,7 +101,9 @@ assert.deepEqual(obj1, obj4);
If the values are not equal, an `AssertionError` is thrown with a `message`
property set equal to the value of the `message` parameter. If the `message`
parameter is undefined, a default error message is assigned.
parameter is undefined, a default error message is assigned. If the `message`
parameter is an instance of an `Error` then it will be thrown instead of the
`AssertionError`.
## assert.deepStrictEqual(actual, expected[, message])
<!-- YAML
@ -176,7 +178,9 @@ assert.deepStrictEqual(NaN, NaN);
If the values are not equal, an `AssertionError` is thrown with a `message`
property set equal to the value of the `message` parameter. If the `message`
parameter is undefined, a default error message is assigned.
parameter is undefined, a default error message is assigned. If the `message`
parameter is an instance of an `Error` then it will be thrown instead of the
`AssertionError`.
## assert.doesNotThrow(block[, error][, message])
<!-- YAML
@ -270,7 +274,9 @@ assert.equal({ a: { b: 1 } }, { a: { b: 1 } });
If the values are not equal, an `AssertionError` is thrown with a `message`
property set equal to the value of the `message` parameter. If the `message`
parameter is undefined, a default error message is assigned.
parameter is undefined, a default error message is assigned. If the `message`
parameter is an instance of an `Error` then it will be thrown instead of the
`AssertionError`.
## assert.fail([message])
## assert.fail(actual, expected[, message[, operator[, stackStartFunction]]])
@ -284,13 +290,15 @@ added: v0.1.21
* `stackStartFunction` {function} (default: `assert.fail`)
Throws an `AssertionError`. If `message` is falsy, the error message is set as
the values of `actual` and `expected` separated by the provided `operator`.
If just the two `actual` and `expected` arguments are provided, `operator` will
default to `'!='`. If `message` is provided only it will be used as the error
message, the other arguments will be stored as properties on the thrown object.
If `stackStartFunction` is provided, all stack frames above that function will
be removed from stacktrace (see [`Error.captureStackTrace`]). If no arguments
are given, the default message `Failed` will be used.
the values of `actual` and `expected` separated by the provided `operator`. If
the `message` parameter is an instance of an `Error` then it will be thrown
instead of the `AssertionError`. If just the two `actual` and `expected`
arguments are provided, `operator` will default to `'!='`. If `message` is
provided only it will be used as the error message, the other arguments will be
stored as properties on the thrown object. If `stackStartFunction` is provided,
all stack frames above that function will be removed from stacktrace (see
[`Error.captureStackTrace`]). If no arguments are given, the default message
`Failed` will be used.
```js
const assert = require('assert');
@ -303,6 +311,9 @@ assert.fail(1, 2, 'fail');
assert.fail(1, 2, 'whoops', '>');
// AssertionError [ERR_ASSERTION]: whoops
assert.fail(1, 2, new TypeError('need array'));
// TypeError: need array
```
*Note*: Is the last two cases `actual`, `expected`, and `operator` have no
@ -414,7 +425,9 @@ assert.notDeepEqual(obj1, obj4);
If the values are deeply equal, an `AssertionError` is thrown with a `message`
property set equal to the value of the `message` parameter. If the `message`
parameter is undefined, a default error message is assigned.
parameter is undefined, a default error message is assigned. If the `message`
parameter is an instance of an `Error` then it will be thrown instead of the
`AssertionError`.
## assert.notDeepStrictEqual(actual, expected[, message])
<!-- YAML
@ -455,9 +468,11 @@ assert.notDeepStrictEqual({ a: 1 }, { a: '1' });
// OK
```
If the values are deeply and strictly equal, an `AssertionError` is thrown
with a `message` property set equal to the value of the `message` parameter. If
the `message` parameter is undefined, a default error message is assigned.
If the values are deeply and strictly equal, an `AssertionError` is thrown with
a `message` property set equal to the value of the `message` parameter. If the
`message` parameter is undefined, a default error message is assigned. If the
`message` parameter is an instance of an `Error` then it will be thrown instead
of the `AssertionError`.
## assert.notEqual(actual, expected[, message])
<!-- YAML
@ -485,7 +500,9 @@ assert.notEqual(1, '1');
If the values are equal, an `AssertionError` is thrown with a `message`
property set equal to the value of the `message` parameter. If the `message`
parameter is undefined, a default error message is assigned.
parameter is undefined, a default error message is assigned. If the `message`
parameter is an instance of an `Error` then it will be thrown instead of the
`AssertionError`.
## assert.notStrictEqual(actual, expected[, message])
<!-- YAML
@ -513,7 +530,9 @@ assert.notStrictEqual(1, '1');
If the values are strictly equal, an `AssertionError` is thrown with a
`message` property set equal to the value of the `message` parameter. If the
`message` parameter is undefined, a default error message is assigned.
`message` parameter is undefined, a default error message is assigned. If the
`message` parameter is an instance of an `Error` then it will be thrown instead
of the `AssertionError`.
## assert.ok(value[, message])
<!-- YAML
@ -527,7 +546,9 @@ Tests if `value` is truthy. It is equivalent to
If `value` is not truthy, an `AssertionError` is thrown with a `message`
property set equal to the value of the `message` parameter. If the `message`
parameter is `undefined`, a default error message is assigned.
parameter is `undefined`, a default error message is assigned. If the `message`
parameter is an instance of an `Error` then it will be thrown instead of the
`AssertionError`.
```js
const assert = require('assert');
@ -570,7 +591,9 @@ assert.strictEqual(1, '1');
If the values are not strictly equal, an `AssertionError` is thrown with a
`message` property set equal to the value of the `message` parameter. If the
`message` parameter is undefined, a default error message is assigned.
`message` parameter is undefined, a default error message is assigned. If the
`message` parameter is an instance of an `Error` then it will be thrown instead
of the `AssertionError`.
## assert.throws(block[, error][, message])
<!-- YAML

View File

@ -38,6 +38,8 @@ const assert = module.exports = ok;
// display purposes.
function innerFail(actual, expected, message, operator, stackStartFunction) {
if (message instanceof Error) throw message;
throw new errors.AssertionError({
message,
actual,

View File

@ -28,6 +28,17 @@ common.expectsError(() => {
expected: undefined
});
// One arg = Error
common.expectsError(() => {
assert.fail(new TypeError('custom message'));
}, {
type: TypeError,
message: 'custom message',
operator: undefined,
actual: undefined,
expected: undefined
});
// Two args only, operator defaults to '!='
common.expectsError(() => {
assert.fail('first', 'second');
@ -52,6 +63,17 @@ common.expectsError(() => {
expected: 'ignored'
});
// Three args with custom Error
common.expectsError(() => {
assert.fail(typeof 1, 'object', new TypeError('another custom message'));
}, {
type: TypeError,
message: 'another custom message',
operator: undefined,
actual: 'number',
expected: 'object'
});
// No third arg (but a fourth arg)
common.expectsError(() => {
assert.fail('first', 'second', undefined, 'operator');

View File

@ -645,6 +645,34 @@ try {
'Message incorrectly marked as generated');
}
{
let threw = false;
const rangeError = new RangeError('my range');
// verify custom errors
try {
assert.strictEqual(1, 2, rangeError);
} catch (e) {
assert.strictEqual(e, rangeError);
threw = true;
assert.ok(e instanceof RangeError, 'Incorrect error type thrown');
}
assert.ok(threw);
threw = false;
// verify AssertionError is the result from doesNotThrow with custom Error
try {
assert.doesNotThrow(() => {
throw new TypeError('wrong type');
}, TypeError, rangeError);
} catch (e) {
threw = true;
assert.ok(e.message.includes(rangeError.message));
assert.ok(e instanceof assert.AssertionError);
}
assert.ok(threw);
}
{
// Verify that throws() and doesNotThrow() throw on non-function block
function typeName(value) {