Skip to content

Commit d47b678

Browse files
committed
assert: wrap validation function errors
This makes sure that validation function used by `assert.throws` and `assert.rejects` always throw validatin errors instead of rethrowing the received error. That should improve the debugging experience for developers since they have a better context where the error is coming from and they also get to know what triggered it. PR-URL: #28263 Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 0b3242c commit d47b678

File tree

4 files changed

+50
-1
lines changed

4 files changed

+50
-1
lines changed

doc/api/assert.md

+3
Original file line numberDiff line numberDiff line change
@@ -1222,6 +1222,9 @@ assert.throws(
12221222

12231223
Custom error validation:
12241224

1225+
The function must return `true` to indicate all internal validations passed.
1226+
It will otherwise fail with an AssertionError.
1227+
12251228
```js
12261229
assert.throws(
12271230
() => {

lib/assert.js

+15-1
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,21 @@ function expectedException(actual, expected, message, fn) {
653653
// Check validation functions return value.
654654
const res = expected.call({}, actual);
655655
if (res !== true) {
656-
throw actual;
656+
if (!message) {
657+
generatedMessage = true;
658+
const name = expected.name ? `"${expected.name}" ` : '';
659+
message = `The ${name}validation function is expected to return "true".` +
660+
` Received ${inspect(res)}`;
661+
}
662+
const err = new AssertionError({
663+
actual,
664+
expected,
665+
message,
666+
operator: fn.name,
667+
stackStartFn: fn
668+
});
669+
err.generatedMessage = generatedMessage;
670+
throw err;
657671
}
658672
}
659673

test/parallel/test-assert-async.js

+15
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,21 @@ const invalidThenableFunc = () => {
6666
code: 'ERR_INVALID_RETURN_VALUE'
6767
})
6868
);
69+
70+
const err = new Error('foobar');
71+
const validate = () => { return 'baz'; };
72+
promises.push(assert.rejects(
73+
() => assert.rejects(Promise.reject(err), validate),
74+
{
75+
message: 'The "validate" validation function is expected to ' +
76+
"return \"true\". Received 'baz'",
77+
code: 'ERR_ASSERTION',
78+
actual: err,
79+
expected: validate,
80+
name: 'AssertionError',
81+
operator: 'rejects',
82+
}
83+
));
6984
}
7085

7186
{

test/parallel/test-assert.js

+17
Original file line numberDiff line numberDiff line change
@@ -1326,3 +1326,20 @@ assert.throws(
13261326
'Received "[Array]"'
13271327
}
13281328
);
1329+
1330+
{
1331+
const err = new TypeError('foo');
1332+
const validate = (() => () => ({ a: true, b: [ 1, 2, 3 ] }))();
1333+
assert.throws(
1334+
() => assert.throws(() => { throw err; }, validate),
1335+
{
1336+
message: 'The validation function is expected to ' +
1337+
`return "true". Received ${inspect(validate())}`,
1338+
code: 'ERR_ASSERTION',
1339+
actual: err,
1340+
expected: validate,
1341+
name: 'AssertionError',
1342+
operator: 'throws',
1343+
}
1344+
);
1345+
}

0 commit comments

Comments
 (0)