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` 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` 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]) ## assert.deepStrictEqual(actual, expected[, message])
<!-- YAML <!-- YAML
@ -176,7 +178,9 @@ assert.deepStrictEqual(NaN, NaN);
If the values are not equal, an `AssertionError` is thrown with a `message` 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` 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]) ## assert.doesNotThrow(block[, error][, message])
<!-- YAML <!-- 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` 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` 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([message])
## assert.fail(actual, expected[, message[, operator[, stackStartFunction]]]) ## assert.fail(actual, expected[, message[, operator[, stackStartFunction]]])
@ -284,13 +290,15 @@ added: v0.1.21
* `stackStartFunction` {function} (default: `assert.fail`) * `stackStartFunction` {function} (default: `assert.fail`)
Throws an `AssertionError`. If `message` is falsy, the error message is set as Throws an `AssertionError`. If `message` is falsy, the error message is set as
the values of `actual` and `expected` separated by the provided `operator`. the values of `actual` and `expected` separated by the provided `operator`. If
If just the two `actual` and `expected` arguments are provided, `operator` will the `message` parameter is an instance of an `Error` then it will be thrown
default to `'!='`. If `message` is provided only it will be used as the error instead of the `AssertionError`. If just the two `actual` and `expected`
message, the other arguments will be stored as properties on the thrown object. arguments are provided, `operator` will default to `'!='`. If `message` is
If `stackStartFunction` is provided, all stack frames above that function will provided only it will be used as the error message, the other arguments will be
be removed from stacktrace (see [`Error.captureStackTrace`]). If no arguments stored as properties on the thrown object. If `stackStartFunction` is provided,
are given, the default message `Failed` will be used. 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 ```js
const assert = require('assert'); const assert = require('assert');
@ -303,6 +311,9 @@ assert.fail(1, 2, 'fail');
assert.fail(1, 2, 'whoops', '>'); assert.fail(1, 2, 'whoops', '>');
// AssertionError [ERR_ASSERTION]: 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 *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` 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` 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]) ## assert.notDeepStrictEqual(actual, expected[, message])
<!-- YAML <!-- YAML
@ -455,9 +468,11 @@ assert.notDeepStrictEqual({ a: 1 }, { a: '1' });
// OK // OK
``` ```
If the values are deeply and strictly equal, an `AssertionError` is thrown If the values are deeply and strictly equal, an `AssertionError` is thrown with
with a `message` property set equal to the value of the `message` parameter. If a `message` property set equal to the value of the `message` parameter. If the
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.notEqual(actual, expected[, message]) ## assert.notEqual(actual, expected[, message])
<!-- YAML <!-- YAML
@ -485,7 +500,9 @@ assert.notEqual(1, '1');
If the values are equal, an `AssertionError` is thrown with a `message` 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` 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]) ## assert.notStrictEqual(actual, expected[, message])
<!-- YAML <!-- YAML
@ -513,7 +530,9 @@ assert.notStrictEqual(1, '1');
If the values are strictly equal, an `AssertionError` is thrown with a 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` 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]) ## assert.ok(value[, message])
<!-- YAML <!-- 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` 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` 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 ```js
const assert = require('assert'); 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 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` 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]) ## assert.throws(block[, error][, message])
<!-- YAML <!-- YAML

View File

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

View File

@ -28,6 +28,17 @@ common.expectsError(() => {
expected: undefined 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 '!=' // Two args only, operator defaults to '!='
common.expectsError(() => { common.expectsError(() => {
assert.fail('first', 'second'); assert.fail('first', 'second');
@ -52,6 +63,17 @@ common.expectsError(() => {
expected: 'ignored' 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) // No third arg (but a fourth arg)
common.expectsError(() => { common.expectsError(() => {
assert.fail('first', 'second', undefined, 'operator'); assert.fail('first', 'second', undefined, 'operator');

View File

@ -645,6 +645,34 @@ try {
'Message incorrectly marked as generated'); '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 // Verify that throws() and doesNotThrow() throw on non-function block
function typeName(value) { function typeName(value) {