Skip to content

Commit f135786

Browse files
committed
assert: support custom errors
1 parent 61e9ba1 commit f135786

File tree

4 files changed

+93
-18
lines changed

4 files changed

+93
-18
lines changed

doc/api/assert.md

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,9 @@ assert.deepEqual(obj1, obj4);
101101

102102
If the values are not equal, an `AssertionError` is thrown with a `message`
103103
property set equal to the value of the `message` parameter. If the `message`
104-
parameter is undefined, a default error message is assigned.
104+
parameter is undefined, a default error message is assigned. If the `message`
105+
parameter is an instance of an `Error` then it will be thrown instead of the
106+
`AssertionError`.
105107

106108
## assert.deepStrictEqual(actual, expected[, message])
107109
<!-- YAML
@@ -174,7 +176,9 @@ assert.deepStrictEqual(NaN, NaN);
174176

175177
If the values are not equal, an `AssertionError` is thrown with a `message`
176178
property set equal to the value of the `message` parameter. If the `message`
177-
parameter is undefined, a default error message is assigned.
179+
parameter is undefined, a default error message is assigned. If the `message`
180+
parameter is an instance of an `Error` then it will be thrown instead of the
181+
`AssertionError`.
178182

179183
## assert.doesNotThrow(block[, error][, message])
180184
<!-- YAML
@@ -268,7 +272,9 @@ assert.equal({ a: { b: 1 } }, { a: { b: 1 } });
268272

269273
If the values are not equal, an `AssertionError` is thrown with a `message`
270274
property set equal to the value of the `message` parameter. If the `message`
271-
parameter is undefined, a default error message is assigned.
275+
parameter is undefined, a default error message is assigned. If the `message`
276+
parameter is an instance of an `Error` then it will be thrown instead of the
277+
`AssertionError`.
272278

273279
## assert.fail([message])
274280
## assert.fail(actual, expected[, message[, operator[, stackStartFunction]]])
@@ -282,13 +288,15 @@ added: v0.1.21
282288
* `stackStartFunction` {function} (default: `assert.fail`)
283289

284290
Throws an `AssertionError`. If `message` is falsy, the error message is set as
285-
the values of `actual` and `expected` separated by the provided `operator`.
286-
If just the two `actual` and `expected` arguments are provided, `operator` will
287-
default to `'!='`. If `message` is provided only it will be used as the error
288-
message, the other arguments will be stored as properties on the thrown object.
289-
If `stackStartFunction` is provided, all stack frames above that function will
290-
be removed from stacktrace (see [`Error.captureStackTrace`]). If no arguments
291-
are given, the default message `Failed` will be used.
291+
the values of `actual` and `expected` separated by the provided `operator`. If
292+
the `message` parameter is an instance of an `Error` then it will be thrown
293+
instead of the `AssertionError`. If just the two `actual` and `expected`
294+
arguments are provided, `operator` will default to `'!='`. If `message` is
295+
provided only it will be used as the error message, the other arguments will be
296+
stored as properties on the thrown object. If `stackStartFunction` is provided,
297+
all stack frames above that function will be removed from stacktrace (see
298+
[`Error.captureStackTrace`]). If no arguments are given, the default message
299+
`Failed` will be used.
292300

293301
```js
294302
const assert = require('assert');
@@ -301,6 +309,9 @@ assert.fail(1, 2, 'fail');
301309

302310
assert.fail(1, 2, 'whoops', '>');
303311
// AssertionError [ERR_ASSERTION]: whoops
312+
313+
assert.fail(1, 2, new TypeError('need array'));
314+
// TypeError: need array
304315
```
305316

306317
*Note*: Is the last two cases `actual`, `expected`, and `operator` have no
@@ -412,7 +423,9 @@ assert.notDeepEqual(obj1, obj4);
412423

413424
If the values are deeply equal, an `AssertionError` is thrown with a `message`
414425
property set equal to the value of the `message` parameter. If the `message`
415-
parameter is undefined, a default error message is assigned.
426+
parameter is undefined, a default error message is assigned. If the `message`
427+
parameter is an instance of an `Error` then it will be thrown instead of the
428+
`AssertionError`.
416429

417430
## assert.notDeepStrictEqual(actual, expected[, message])
418431
<!-- YAML
@@ -453,9 +466,11 @@ assert.notDeepStrictEqual({ a: 1 }, { a: '1' });
453466
// OK
454467
```
455468

456-
If the values are deeply and strictly equal, an `AssertionError` is thrown
457-
with a `message` property set equal to the value of the `message` parameter. If
458-
the `message` parameter is undefined, a default error message is assigned.
469+
If the values are deeply and strictly equal, an `AssertionError` is thrown with
470+
a `message` property set equal to the value of the `message` parameter. If the
471+
`message` parameter is undefined, a default error message is assigned. If the
472+
`message` parameter is an instance of an `Error` then it will be thrown instead
473+
of the `AssertionError`.
459474

460475
## assert.notEqual(actual, expected[, message])
461476
<!-- YAML
@@ -483,7 +498,9 @@ assert.notEqual(1, '1');
483498

484499
If the values are equal, an `AssertionError` is thrown with a `message`
485500
property set equal to the value of the `message` parameter. If the `message`
486-
parameter is undefined, a default error message is assigned.
501+
parameter is undefined, a default error message is assigned. If the `message`
502+
parameter is an instance of an `Error` then it will be thrown instead of the
503+
`AssertionError`.
487504

488505
## assert.notStrictEqual(actual, expected[, message])
489506
<!-- YAML
@@ -511,7 +528,9 @@ assert.notStrictEqual(1, '1');
511528

512529
If the values are strictly equal, an `AssertionError` is thrown with a
513530
`message` property set equal to the value of the `message` parameter. If the
514-
`message` parameter is undefined, a default error message is assigned.
531+
`message` parameter is undefined, a default error message is assigned. If the
532+
`message` parameter is an instance of an `Error` then it will be thrown instead
533+
of the `AssertionError`.
515534

516535
## assert.ok(value[, message])
517536
<!-- YAML
@@ -525,7 +544,9 @@ Tests if `value` is truthy. It is equivalent to
525544

526545
If `value` is not truthy, an `AssertionError` is thrown with a `message`
527546
property set equal to the value of the `message` parameter. If the `message`
528-
parameter is `undefined`, a default error message is assigned.
547+
parameter is `undefined`, a default error message is assigned. If the `message`
548+
parameter is an instance of an `Error` then it will be thrown instead of the
549+
`AssertionError`.
529550

530551
```js
531552
const assert = require('assert');
@@ -568,7 +589,9 @@ assert.strictEqual(1, '1');
568589

569590
If the values are not strictly equal, an `AssertionError` is thrown with a
570591
`message` property set equal to the value of the `message` parameter. If the
571-
`message` parameter is undefined, a default error message is assigned.
592+
`message` parameter is undefined, a default error message is assigned. If the
593+
`message` parameter is an instance of an `Error` then it will be thrown instead
594+
of the `AssertionError`.
572595

573596
## assert.throws(block[, error][, message])
574597
<!-- YAML

lib/assert.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ const assert = module.exports = ok;
3838
// display purposes.
3939

4040
function innerFail(actual, expected, message, operator, stackStartFunction) {
41+
if (message instanceof Error) throw message;
42+
4143
throw new errors.AssertionError({
4244
message,
4345
actual,

test/parallel/test-assert-fail.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,17 @@ common.expectsError(() => {
2828
expected: undefined
2929
});
3030

31+
// One arg = Error
32+
common.expectsError(() => {
33+
assert.fail(new TypeError('custom message'));
34+
}, {
35+
type: TypeError,
36+
message: 'custom message',
37+
operator: undefined,
38+
actual: undefined,
39+
expected: undefined
40+
});
41+
3142
// Two args only, operator defaults to '!='
3243
common.expectsError(() => {
3344
assert.fail('first', 'second');
@@ -52,6 +63,17 @@ common.expectsError(() => {
5263
expected: 'ignored'
5364
});
5465

66+
// Three args with custom Error
67+
common.expectsError(() => {
68+
assert.fail(typeof 1, 'object', new TypeError('another custom message'));
69+
}, {
70+
type: TypeError,
71+
message: 'another custom message',
72+
operator: undefined,
73+
actual: 'number',
74+
expected: 'object'
75+
});
76+
5577
// No third arg (but a fourth arg)
5678
common.expectsError(() => {
5779
assert.fail('first', 'second', undefined, 'operator');

test/parallel/test-assert.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,34 @@ try {
645645
'Message incorrectly marked as generated');
646646
}
647647

648+
{
649+
let threw = false;
650+
const rangeError = new RangeError('my range');
651+
652+
// verify custom errors
653+
try {
654+
assert.strictEqual(1, 2, rangeError);
655+
} catch (e) {
656+
assert.strictEqual(e, rangeError);
657+
threw = true;
658+
assert.ok(e instanceof RangeError, 'Incorrect error type thrown');
659+
}
660+
assert.ok(threw);
661+
threw = false;
662+
663+
// verify AssertionError is the result from doesNotThrow with custom Error
664+
try {
665+
assert.doesNotThrow(() => {
666+
throw new TypeError('wrong type');
667+
}, TypeError, rangeError);
668+
} catch (e) {
669+
threw = true;
670+
assert.ok(e.message.includes(rangeError.message));
671+
assert.ok(e instanceof assert.AssertionError);
672+
}
673+
assert.ok(threw);
674+
}
675+
648676
{
649677
// Verify that throws() and doesNotThrow() throw on non-function block
650678
function typeName(value) {

0 commit comments

Comments
 (0)