diff --git a/doc/api/assert.md b/doc/api/assert.md
index d2b541111586be..dbd32096b5c096 100644
--- a/doc/api/assert.md
+++ b/doc/api/assert.md
@@ -7,6 +7,57 @@
The `assert` module provides a simple set of assertion tests that can be used to
test invariants.
+A `strict` and a `legacy` mode exist, while it is recommended to only use
+[`strict mode`][].
+
+For more information about the used equality comparisons see
+[MDN's guide on equality comparisons and sameness][mdn-equality-guide].
+
+## Strict mode
+
+
+When using the `strict mode`, any `assert` function will use the equality used in
+the strict function mode. So [`assert.deepEqual()`][] will, for example, work the
+same as [`assert.deepStrictEqual()`][].
+
+It can be accessed using:
+
+```js
+const assert = require('assert').strict;
+```
+
+## Legacy mode
+
+> Stability: 0 - Deprecated: Use strict mode instead.
+
+When accessing `assert` directly instead of using the `strict` property, the
+[Abstract Equality Comparison][] will be used for any function without a
+"strict" in its name (e.g. [`assert.deepEqual()`][]).
+
+It can be accessed using:
+
+```js
+const assert = require('assert');
+```
+
+It is recommended to use the [`strict mode`][] instead as the
+[Abstract Equality Comparison][] can often have surprising results. Especially
+in case of [`assert.deepEqual()`][] as the used comparison rules there are very
+lax.
+
+E.g.
+
+```js
+// WARNING: This does not throw an AssertionError!
+assert.deepEqual(/a/gi, new Date());
+```
+
## assert(value[, message])
* `block` {Function}
-* `error` {RegExp|Function}
+* `error` {RegExp|Function|object}
* `message` {any}
Expects the function `block` to throw an error.
-If specified, `error` can be a constructor, [`RegExp`][], or validation
-function.
+If specified, `error` can be a constructor, [`RegExp`][], a validation
+function, or an object where each property will be tested for.
If specified, `message` will be the message provided by the `AssertionError` if
the block fails to throw.
@@ -596,19 +692,61 @@ assert.throws(
);
```
+Custom error object / error instance:
+
+```js
+assert.throws(
+ () => {
+ const err = new TypeError('Wrong value');
+ err.code = 404;
+ throw err;
+ },
+ {
+ name: 'TypeError',
+ message: 'Wrong value'
+ // Note that only properties on the error object will be tested!
+ }
+);
+```
+
Note that `error` can not be a string. If a string is provided as the second
argument, then `error` is assumed to be omitted and the string will be used for
-`message` instead. This can lead to easy-to-miss mistakes:
+`message` instead. This can lead to easy-to-miss mistakes. Please read the
+example below carefully if using a string as the second argument gets
+considered:
```js
-// THIS IS A MISTAKE! DO NOT DO THIS!
-assert.throws(myFunction, 'missing foo', 'did not throw with expected message');
-
-// Do this instead.
-assert.throws(myFunction, /missing foo/, 'did not throw with expected message');
+function throwingFirst() {
+ throw new Error('First');
+}
+function throwingSecond() {
+ throw new Error('Second');
+}
+function notThrowing() {}
+
+// The second argument is a string and the input function threw an Error.
+// In that case both cases do not throw as neither is going to try to
+// match for the error message thrown by the input function!
+assert.throws(throwingFirst, 'Second');
+assert.throws(throwingSecond, 'Second');
+
+// The string is only used (as message) in case the function does not throw:
+assert.throws(notThrowing, 'Second');
+// AssertionError [ERR_ASSERTION]: Missing expected exception: Second
+
+// If it was intended to match for the error message do this instead:
+assert.throws(throwingSecond, /Second$/);
+// Does not throw because the error messages match.
+assert.throws(throwingFirst, /Second$/);
+// Throws a error:
+// Error: First
+// at throwingFirst (repl:2:9)
```
+Due to the confusing notation, it is recommended not to use a string as the
+second argument. This might lead to difficult-to-spot errors.
+
## Caveats
For the following cases, consider using ES2015 [`Object.is()`][],
@@ -643,8 +781,12 @@ For more information, see
[`TypeError`]: errors.html#errors_class_typeerror
[`assert.deepEqual()`]: #assert_assert_deepequal_actual_expected_message
[`assert.deepStrictEqual()`]: #assert_assert_deepstrictequal_actual_expected_message
+[`assert.notDeepStrictEqual()`]: #assert_assert_notdeepstrictequal_actual_expected_message
+[`assert.notStrictEqual()`]: #assert_assert_notstrictequal_actual_expected_message
[`assert.ok()`]: #assert_assert_ok_value_message
+[`assert.strictEqual()`]: #assert_assert_strictequal_actual_expected_message
[`assert.throws()`]: #assert_assert_throws_block_error_message
+[`strict mode`]: #assert_strict_mode
[Abstract Equality Comparison]: https://tc39.github.io/ecma262/#sec-abstract-equality-comparison
[Object.prototype.toString()]: https://tc39.github.io/ecma262/#sec-object.prototype.tostring
[SameValueZero]: https://tc39.github.io/ecma262/#sec-samevaluezero
diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md
index efa939c5779b55..12a73f8878c855 100644
--- a/doc/api/deprecations.md
+++ b/doc/api/deprecations.md
@@ -684,6 +684,15 @@ Type: Runtime
cause a lot of issues. See https://github.com/nodejs/node/issues/14328 for more
details.
+
+### DEP0089: require('assert')
+
+Type: Documentation-only
+
+Importing assert directly is not recommended as the exposed functions will use
+loose equality checks. Use `require('assert').strict` instead. The API is the
+same as the legacy assert but it will always use strict equality checks.
+
### DEP0098: AsyncHooks Embedder AsyncResource.emit{Before,After} APIs
diff --git a/lib/assert.js b/lib/assert.js
index 3418cf3230f83f..ad568547b45c6a 100644
--- a/lib/assert.js
+++ b/lib/assert.js
@@ -25,6 +25,7 @@ const { isSet, isMap, isDate, isRegExp } = process.binding('util');
const { objectToString } = require('internal/util');
const { isArrayBufferView } = require('internal/util/types');
const errors = require('internal/errors');
+const { inspect } = require('util');
// The assert module provides functions that throw
// AssertionError's when particular conditions are not met. The
@@ -38,22 +39,26 @@ const assert = module.exports = ok;
// both the actual and expected values to the assertion error for
// display purposes.
-function innerFail(actual, expected, message, operator, stackStartFunction) {
- throw new errors.AssertionError({
- message,
- actual,
- expected,
- operator,
- stackStartFunction
- });
+function innerFail(obj) {
+ throw new errors.AssertionError(obj);
}
-function fail(actual, expected, message, operator, stackStartFunction) {
- if (arguments.length === 1)
+function fail(actual, expected, message, operator, stackStartFn) {
+ const argsLen = arguments.length;
+
+ if (argsLen === 1) {
message = actual;
- if (arguments.length === 2)
+ } else if (argsLen === 2) {
operator = '!=';
- innerFail(actual, expected, message, operator, stackStartFunction || fail);
+ }
+
+ innerFail({
+ actual,
+ expected,
+ message,
+ operator,
+ stackStartFn: stackStartFn || fail
+ });
}
assert.fail = fail;
@@ -67,7 +72,15 @@ assert.AssertionError = errors.AssertionError;
// Pure assertion tests whether a value is truthy, as determined
// by !!value.
function ok(value, message) {
- if (!value) innerFail(value, true, message, '==', ok);
+ if (!value) {
+ innerFail({
+ actual: value,
+ expected: true,
+ message,
+ operator: '==',
+ stackStartFn: ok
+ });
+ }
}
assert.ok = ok;
@@ -75,7 +88,15 @@ assert.ok = ok;
/* eslint-disable no-restricted-properties */
assert.equal = function equal(actual, expected, message) {
// eslint-disable-next-line eqeqeq
- if (actual != expected) innerFail(actual, expected, message, '==', equal);
+ if (actual != expected) {
+ innerFail({
+ actual,
+ expected,
+ message,
+ operator: '==',
+ stackStartFn: equal
+ });
+ }
};
// The non-equality assertion tests for whether two objects are not
@@ -83,21 +104,39 @@ assert.equal = function equal(actual, expected, message) {
assert.notEqual = function notEqual(actual, expected, message) {
// eslint-disable-next-line eqeqeq
if (actual == expected) {
- innerFail(actual, expected, message, '!=', notEqual);
+ innerFail({
+ actual,
+ expected,
+ message,
+ operator: '!=',
+ stackStartFn: notEqual
+ });
}
};
// The equivalence assertion tests a deep equality relation.
assert.deepEqual = function deepEqual(actual, expected, message) {
if (!innerDeepEqual(actual, expected, false)) {
- innerFail(actual, expected, message, 'deepEqual', deepEqual);
+ innerFail({
+ actual,
+ expected,
+ message,
+ operator: 'deepEqual',
+ stackStartFn: deepEqual
+ });
}
};
/* eslint-enable */
assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) {
if (!innerDeepEqual(actual, expected, true)) {
- innerFail(actual, expected, message, 'deepStrictEqual', deepStrictEqual);
+ innerFail({
+ actual,
+ expected,
+ message,
+ operator: 'deepStrictEqual',
+ stackStartFn: deepStrictEqual
+ });
}
};
@@ -572,22 +611,39 @@ function objEquiv(a, b, strict, keys, memos) {
// The non-equivalence assertion tests for any deep inequality.
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
if (innerDeepEqual(actual, expected, false)) {
- innerFail(actual, expected, message, 'notDeepEqual', notDeepEqual);
+ innerFail({
+ actual,
+ expected,
+ message,
+ operator: 'notDeepEqual',
+ stackStartFn: notDeepEqual
+ });
}
};
assert.notDeepStrictEqual = notDeepStrictEqual;
function notDeepStrictEqual(actual, expected, message) {
if (innerDeepEqual(actual, expected, true)) {
- innerFail(actual, expected, message, 'notDeepStrictEqual',
- notDeepStrictEqual);
+ innerFail({
+ actual,
+ expected,
+ message,
+ operator: 'notDeepStrictEqual',
+ stackStartFn: notDeepStrictEqual
+ });
}
}
// The strict equality assertion tests strict equality, as determined by ===.
assert.strictEqual = function strictEqual(actual, expected, message) {
if (actual !== expected) {
- innerFail(actual, expected, message, '===', strictEqual);
+ innerFail({
+ actual,
+ expected,
+ message,
+ operator: '===',
+ stackStartFn: strictEqual
+ });
}
};
@@ -595,14 +651,50 @@ assert.strictEqual = function strictEqual(actual, expected, message) {
// determined by !==.
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
if (actual === expected) {
- innerFail(actual, expected, message, '!==', notStrictEqual);
+ innerFail({
+ actual,
+ expected,
+ message,
+ operator: '!==',
+ stackStartFn: notStrictEqual
+ });
}
};
-function expectedException(actual, expected) {
+function compareExceptionKey(actual, expected, key, msg) {
+ if (!innerDeepEqual(actual[key], expected[key], true)) {
+ innerFail({
+ actual: actual[key],
+ expected: expected[key],
+ message: msg || `${key}: expected ${inspect(expected[key])}, ` +
+ `not ${inspect(actual[key])}`,
+ operator: 'throws',
+ stackStartFn: assert.throws
+ });
+ }
+}
+
+function expectedException(actual, expected, msg) {
if (typeof expected !== 'function') {
- // Should be a RegExp, if not fail hard
- return expected.test(actual);
+ if (expected instanceof RegExp)
+ return expected.test(actual);
+ // assert.doesNotThrow does not accept objects.
+ if (arguments.length === 2) {
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'expected',
+ ['Function', 'RegExp'], expected);
+ }
+ // The name and message could be non enumerable. Therefore test them
+ // explicitly.
+ if ('name' in expected) {
+ compareExceptionKey(actual, expected, 'name', msg);
+ }
+ if ('message' in expected) {
+ compareExceptionKey(actual, expected, 'message', msg);
+ }
+ for (const key of Object.keys(expected)) {
+ compareExceptionKey(actual, expected, key, msg);
+ }
+ return true;
}
// Guard instanceof against arrow functions as they don't have a prototype.
if (expected.prototype !== undefined && actual instanceof expected) {
@@ -614,7 +706,11 @@ function expectedException(actual, expected) {
return expected.call({}, actual) === true;
}
-function tryBlock(block) {
+function getActual(block) {
+ if (typeof block !== 'function') {
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'block', 'Function',
+ block);
+ }
try {
block();
} catch (e) {
@@ -622,48 +718,81 @@ function tryBlock(block) {
}
}
-function innerThrows(shouldThrow, block, expected, message) {
- var details = '';
+// Expected to throw an error.
+assert.throws = function throws(block, error, message) {
+ const actual = getActual(block);
- if (typeof block !== 'function') {
- throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'block', 'function',
- block);
- }
+ if (typeof error === 'string') {
+ if (arguments.length === 3)
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
+ 'error',
+ ['Function', 'RegExp'],
+ error);
- if (typeof expected === 'string') {
- message = expected;
- expected = null;
+ message = error;
+ error = null;
}
- const actual = tryBlock(block);
-
- if (shouldThrow === true) {
- if (actual === undefined) {
- if (expected && expected.name) {
- details += ` (${expected.name})`;
- }
- details += message ? `: ${message}` : '.';
- fail(actual, expected, `Missing expected exception${details}`, fail);
- }
- if (expected && expectedException(actual, expected) === false) {
- throw actual;
- }
- } else if (actual !== undefined) {
- if (!expected || expectedException(actual, expected)) {
- details = message ? `: ${message}` : '.';
- fail(actual, expected, `Got unwanted exception${details}`, fail);
+ if (actual === undefined) {
+ let details = '';
+ if (error && error.name) {
+ details += ` (${error.name})`;
}
+ details += message ? `: ${message}` : '.';
+ innerFail({
+ actual,
+ expected: error,
+ operator: 'throws',
+ message: `Missing expected exception${details}`,
+ stackStartFn: throws
+ });
+ }
+ if (error && expectedException(actual, error, message) === false) {
throw actual;
}
-}
-
-// Expected to throw an error.
-assert.throws = function throws(block, error, message) {
- innerThrows(true, block, error, message);
};
assert.doesNotThrow = function doesNotThrow(block, error, message) {
- innerThrows(false, block, error, message);
+ const actual = getActual(block);
+ if (actual === undefined)
+ return;
+
+ if (typeof error === 'string') {
+ message = error;
+ error = null;
+ }
+
+ if (!error || expectedException(actual, error)) {
+ const details = message ? `: ${message}` : '.';
+ innerFail({
+ actual,
+ expected: error,
+ operator: 'doesNotThrow',
+ message: `Got unwanted exception${details}\n${actual.message}`,
+ stackStartFn: doesNotThrow
+ });
+ }
+ throw actual;
};
assert.ifError = function ifError(err) { if (err) throw err; };
+
+// Expose a strict only variant of assert
+function strict(value, message) {
+ if (!value) {
+ innerFail({
+ actual: value,
+ expected: true,
+ message,
+ operator: '==',
+ stackStartFn: strict
+ });
+ }
+}
+assert.strict = Object.assign(strict, assert, {
+ equal: assert.strictEqual,
+ deepEqual: assert.deepStrictEqual,
+ notEqual: assert.notStrictEqual,
+ notDeepEqual: assert.notDeepStrictEqual
+});
+assert.strict.strict = assert.strict;
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index e62ce3fb22759a..590ab57bdb4e5d 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -80,7 +80,7 @@ class AssertionError extends Error {
if (typeof options !== 'object' || options === null) {
throw new exports.TypeError('ERR_INVALID_ARG_TYPE', 'options', 'object');
}
- var { actual, expected, message, operator, stackStartFunction } = options;
+ var { actual, expected, message, operator, stackStartFn } = options;
if (message) {
super(message);
} else {
@@ -99,7 +99,7 @@ class AssertionError extends Error {
this.actual = actual;
this.expected = expected;
this.operator = operator;
- Error.captureStackTrace(this, stackStartFunction);
+ Error.captureStackTrace(this, stackStartFn);
}
}
diff --git a/test/message/assert_throws_stack.js b/test/message/assert_throws_stack.js
new file mode 100644
index 00000000000000..36bc5734cae37f
--- /dev/null
+++ b/test/message/assert_throws_stack.js
@@ -0,0 +1,6 @@
+'use strict';
+
+require('../common');
+const assert = require('assert').strict;
+
+assert.throws(() => { throw new Error('foo'); }, { bar: true });
diff --git a/test/message/assert_throws_stack.out b/test/message/assert_throws_stack.out
new file mode 100644
index 00000000000000..04e62b98139eed
--- /dev/null
+++ b/test/message/assert_throws_stack.out
@@ -0,0 +1,14 @@
+assert.js:*
+ throw new errors.AssertionError(obj);
+ ^
+
+AssertionError [ERR_ASSERTION]: bar: expected true, not undefined
+ at Object. (*assert_throws_stack.js:*:*)
+ at *
+ at *
+ at *
+ at *
+ at *
+ at *
+ at *
+ at *
diff --git a/test/message/error_exit.out b/test/message/error_exit.out
index d6fbded760106b..c2dfc6a9f910ca 100644
--- a/test/message/error_exit.out
+++ b/test/message/error_exit.out
@@ -1,6 +1,6 @@
Exiting with code=1
assert.js:*
- throw new errors.AssertionError({
+ throw new errors.AssertionError(obj);
^
AssertionError [ERR_ASSERTION]: 1 === 2
diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js
index c73b49deb328cb..08b81b7c37f7fa 100644
--- a/test/parallel/test-assert.js
+++ b/test/parallel/test-assert.js
@@ -36,16 +36,6 @@ assert.ok(a.AssertionError.prototype instanceof Error,
assert.throws(makeBlock(a, false), a.AssertionError, 'ok(false)');
-// Using a object as second arg results in a failure
-assert.throws(
- () => { assert.throws(() => { throw new Error(); }, { foo: 'bar' }); },
- common.expectsError({
- type: TypeError,
- message: 'expected.test is not a function'
- })
-);
-
-
assert.doesNotThrow(makeBlock(a, true), a.AssertionError, 'ok(true)');
assert.doesNotThrow(makeBlock(a, 'test', 'ok(\'test\')'));
@@ -463,10 +453,15 @@ assert.throws(() => { assert.ifError(new Error('test error')); },
assert.doesNotThrow(() => { assert.ifError(null); });
assert.doesNotThrow(() => { assert.ifError(); });
-assert.throws(() => {
- assert.doesNotThrow(makeBlock(thrower, Error), 'user message');
-}, /Got unwanted exception: user message/,
- 'a.doesNotThrow ignores user message');
+common.expectsError(
+ () => assert.doesNotThrow(makeBlock(thrower, Error), 'user message'),
+ {
+ type: a.AssertionError,
+ code: 'ERR_ASSERTION',
+ operator: 'doesNotThrow',
+ message: 'Got unwanted exception: user message\n[object Object]'
+ }
+);
// make sure that validating using constructor really works
{
@@ -525,7 +520,8 @@ a.throws(makeBlock(thrower, TypeError), (err) => {
() => { a.throws((noop)); },
common.expectsError({
code: 'ERR_ASSERTION',
- message: /^Missing expected exception\.$/
+ message: /^Missing expected exception\.$/,
+ operator: 'throws'
}));
assert.throws(
@@ -597,6 +593,7 @@ testAssertionMessage({ a: NaN, b: Infinity, c: -Infinity },
} catch (e) {
threw = true;
assert.strictEqual(e.message, 'Missing expected exception.');
+ assert.ok(!e.stack.includes('throws'), e.stack);
}
assert.ok(threw);
}
@@ -613,8 +610,8 @@ try {
assert.strictEqual(1, 2, 'oh no'); // eslint-disable-line no-restricted-syntax
} catch (e) {
assert.strictEqual(e.message.split('\n')[0], 'oh no');
- // Message should not be marked as generated.
- assert.strictEqual(e.generatedMessage, false);
+ assert.strictEqual(e.generatedMessage, false,
+ 'Message incorrectly marked as generated');
}
{
@@ -633,7 +630,7 @@ try {
common.expectsError({
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
- message: 'The "block" argument must be of type function. Received ' +
+ message: 'The "block" argument must be of type Function. Received ' +
`type ${typeName(block)}`
})(e);
}
@@ -696,3 +693,126 @@ common.expectsError(
message: /^'Error: foo' === 'Error: foobar'$/
}
);
+
+// Test strict assert
+{
+ const a = require('assert');
+ const assert = require('assert').strict;
+ /* eslint-disable no-restricted-properties */
+ assert.throws(() => assert.equal(1, true), assert.AssertionError);
+ assert.notEqual(0, false);
+ assert.throws(() => assert.deepEqual(1, true), assert.AssertionError);
+ assert.notDeepEqual(0, false);
+ assert.equal(assert.strict, assert.strict.strict);
+ assert.equal(assert.equal, assert.strictEqual);
+ assert.equal(assert.deepEqual, assert.deepStrictEqual);
+ assert.equal(assert.notEqual, assert.notStrictEqual);
+ assert.equal(assert.notDeepEqual, assert.notDeepStrictEqual);
+ assert.equal(Object.keys(assert).length, Object.keys(a).length);
+ /* eslint-enable no-restricted-properties */
+ assert(7);
+ common.expectsError(
+ () => assert(),
+ {
+ code: 'ERR_ASSERTION',
+ type: assert.AssertionError,
+ message: 'undefined == true'
+ }
+ );
+}
+
+common.expectsError(
+ () => assert.ok(null),
+ {
+ code: 'ERR_ASSERTION',
+ type: assert.AssertionError,
+ message: 'null == true'
+ }
+);
+
+common.expectsError(
+ // eslint-disable-next-line no-restricted-syntax
+ () => assert.throws(() => {}, 'Error message', 'message'),
+ {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError,
+ message: 'The "error" argument must be one of type Function or RegExp. ' +
+ 'Received type string'
+ }
+);
+
+{
+ const errFn = () => {
+ const err = new TypeError('Wrong value');
+ err.code = 404;
+ throw err;
+ };
+ const errObj = {
+ name: 'TypeError',
+ message: 'Wrong value'
+ };
+ assert.throws(errFn, errObj);
+
+ errObj.code = 404;
+ assert.throws(errFn, errObj);
+
+ errObj.code = '404';
+ common.expectsError(
+ // eslint-disable-next-line no-restricted-syntax
+ () => assert.throws(errFn, errObj),
+ {
+ code: 'ERR_ASSERTION',
+ type: assert.AssertionError,
+ message: 'code: expected \'404\', not 404'
+ }
+ );
+
+ errObj.code = 404;
+ errObj.foo = 'bar';
+ common.expectsError(
+ // eslint-disable-next-line no-restricted-syntax
+ () => assert.throws(errFn, errObj),
+ {
+ code: 'ERR_ASSERTION',
+ type: assert.AssertionError,
+ message: 'foo: expected \'bar\', not undefined'
+ }
+ );
+
+ common.expectsError(
+ () => assert.throws(() => { throw new Error(); }, { foo: 'bar' }, 'foobar'),
+ {
+ type: assert.AssertionError,
+ code: 'ERR_ASSERTION',
+ message: 'foobar'
+ }
+ );
+
+ common.expectsError(
+ () => assert.doesNotThrow(() => { throw new Error(); }, { foo: 'bar' }),
+ {
+ type: TypeError,
+ code: 'ERR_INVALID_ARG_TYPE',
+ message: 'The "expected" argument must be one of type Function or ' +
+ 'RegExp. Received type object'
+ }
+ );
+
+ assert.throws(() => { throw new Error('e'); }, new Error('e'));
+ common.expectsError(
+ () => assert.throws(() => { throw new TypeError('e'); }, new Error('e')),
+ {
+ type: assert.AssertionError,
+ code: 'ERR_ASSERTION',
+ message: "name: expected 'Error', not 'TypeError'"
+ }
+ );
+ common.expectsError(
+ () => assert.throws(() => { throw new Error('foo'); }, new Error('')),
+ {
+ type: assert.AssertionError,
+ code: 'ERR_ASSERTION',
+ message: "message: expected '', not 'foo'"
+ }
+ );
+}