nodeJS提供一组assert断言函数,用于验证不变量。
断言类似于布尔值的判断,不同点是断言其实是防止程序意外出错的一种宏,如果其参数计算为假,则程序发出警告,且退出也就是终止程序。这和if语句是不同的。日常开发中基本很少用到断言模块,除非你在写单元测试,其中会涉及到一些断言的语法。
assert是node官方模块包,不需要安装,直接引入即可。
const assert = require('assert');
assert提供的方法都是静态的,可以直接调用。比如assert.ok直接接收一个布尔值,当值为假的时候断言不通过,并且抛出异常。
assert.ok(false);
// assert(false);
AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
assert.ok(false)
at Object.<anonymous> (/Users/choice/Documents/person/blog/test.js:3:8)
at Module._compile (internal/modules/cjs/loader.js:701:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
at Module.load (internal/modules/cjs/loader.js:600:32)
at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
at Function.Module._load (internal/modules/cjs/loader.js:531:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:754:12)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)
- assert.deepEqual()
用于比较两个值是否相等,是一种不严格的比较,除 NaN 之外,其他值均使用==来比较原始值,所以比较中会出现一些奇怪的问题。
如果对比的双方均为 NaN,则视为相同。如果是对象,则要求对象的类型标签应该相同。只考虑可枚举的自身属性。如果是Error则会始终比较 Error 的名称和消息,即使这些不是可枚举的属性。对象封装器作为对象和解封装后的值都进行比较。Object 属性的比较是无序的。Map 键名与 Set 子项的比较是无序的。当两边的值不相同或遇到循环引用时,递归停止。不测试对象的 [[Prototype]]。可枚举的自身 Symbol 属性也会比较。WeakMap 和 WeakSet 的比较不依赖于它们的值。
assert.deepEqual('+00000000', false);
// '+00000000' 会变为false 导致相等
- assert.deepStrictEqual
在新版本的nodeJS中推荐使用assert.deepStrictEqual代替assert.deepEqual,意为严格模式的断言。
assert.deepStrictEqual使用使用 Object.is()来比较原始值,对象的类型标签应该相同。使用严格相等比较来比较对象的原型。同样也只考虑可枚举的自身属性。始终比较 Error 的名称和消息,即使这些不是可枚举的属性。可枚举的自身 Symbol 属性也会比较。对象封装器作为对象和解封装后的值都进行比较。Object 属性的比较是无序的。Map 键名与 Set 子项的比较是无序的。当两边的值不相同或遇到循环引用时,递归停止。WeakMap 和 WeakSet 的比较不依赖于它们的值。
const assert = require('assert').strict;
// 失败,因为 1 !== '1'。
assert.deepStrictEqual({ a: 1 }, { a: '1' });
// 以下对象没有自身属性。
const date = new Date();
const object = {};
const fakeDate = {};
Object.setPrototypeOf(fakeDate, Date.prototype);
// 原型不同:
assert.deepStrictEqual(object, fakeDate);
// 类型标签不同:
assert.deepStrictEqual(date, fakeDate);
// + 2018-04-26T00:49:08.604Z
// - Date {}
assert.deepStrictEqual(NaN, NaN);
// 通过,因为使用 SameValue 比较。
// 解封装后的数字不同:
assert.deepStrictEqual(new Number(1), new Number(2));
assert.deepStrictEqual(new String('foo'), Object('foo'));
// 通过,因为对象与解封装后的字符串都是相同的。
assert.deepStrictEqual(-0, -0);
// 通过。
// 使用 SameValue 比较的零不同:
assert.deepStrictEqual(0, -0);
const symbol1 = Symbol();
const symbol2 = Symbol();
assert.deepStrictEqual({ [symbol1]: 1 }, { [symbol1]: 1 });
// 通过,因为在两个对象上的 symbol 相同。
assert.deepStrictEqual({ [symbol1]: 1 }, { [symbol2]: 1 });
const weakMap1 = new WeakMap();
const weakMap2 = new WeakMap([[{}, {}]]);
const weakMap3 = new WeakMap();
weakMap3.unequal = true;
assert.deepStrictEqual(weakMap1, weakMap2);
// 通过,因为无法比较条目。
// 失败,因为 weakMap3 有一个 weakMap1 不包含的属性:
assert.deepStrictEqual(weakMap1, weakMap3);
- assert.notDeepStrictEqual
测试深度严格的不平等。 与 assert.deepStrictEqual()获得的结果相反相反。
const assert = require('assert').strict;
assert.notDeepStrictEqual({ a: 1 }, { a: '1' });
// 通过。
- doesNotMatch
接收两个参数,第一个参数是字符串,第二个参数是正则,当不匹配时通过。
const assert = require('assert').strict;
assert.doesNotMatch('I will fail', /fail/);
// 不通过
assert.doesNotMatch(123, /pass/);
// 第一个参数必须是字符串
assert.doesNotMatch('I will pass', /different/);
// 通过
- assert.match
接收两个参数,第一个参数是字符串,第二个参数是正则,当匹配时通过。
const assert = require('assert').strict;
assert.match('I will fail', /pass/);
// 不通过
assert.match(123, /pass/);
// 第一个参数必须是字符串
assert.match('I will pass', /pass/);
// 通过
- assert.fail
使用提供的错误消息或默认错误消息抛出 AssertionError。 如果 message 参数是 Error 的实例,则它将被抛出而不是 AssertionError
const assert = require('assert').strict;
assert.fail();
// AssertionError [ERR_ASSERTION]: Failed
assert.fail('失败');
// AssertionError [ERR_ASSERTION]: 失败
assert.fail(new TypeError('需要数组'));
// TypeError: 需要数组
- assert.ifError
如果接收的值 不为 undefined 或 null,则抛出 该值。 在回调中测试 error 参数时,这很有用。 堆栈跟踪包含传递给 ifError() 的错误的所有帧,包括 ifError() 本身的潜在新帧。
const assert = require('assert').strict;
assert.ifError(null);
// 通过。
assert.ifError(0);
// AssertionError [ERR_ASSERTION]: ifError got unwanted exception: 0
assert.ifError('错误');
// AssertionError [ERR_ASSERTION]: ifError got unwanted exception: '错误'
assert.ifError(new Error());
// AssertionError [ERR_ASSERTION]: ifError got unwanted exception: Error
// 创建一些随机错误帧。
let err;
(function errorFrame() {
err = new Error('测试错误');
})();
(function ifErrorFrame() {
assert.ifError(err);
})();
// AssertionError [ERR_ASSERTION]: ifError got unwanted exception: 测试错误
// at ifErrorFrame
// at errorFrame
- assert.notStrictEqual
接收两个参数,测试两个参数之间的严格不相等
const assert = require('assert').strict;
assert.notStrictEqual(1, 2);
// 通过。
assert.notStrictEqual(1, 1);
// AssertionError [ERR_ASSERTION]: Expected "actual" to be strictly unequal to:
//
// 1
assert.notStrictEqual(1, '1');
// 通过。
- assert.strictEqual
比较两个值的严格相等
const assert = require('assert').strict;
assert.strictEqual(1, 2);
// AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal:
//
// 1 !== 2
assert.strictEqual(1, 1);
// OK
assert.strictEqual('Hello foobar', 'Hello World!');
// AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal:
// + actual - expected
//
// + 'Hello foobar'
// - 'Hello World!'
// ^
const apples = 1;
const oranges = 2;
assert.strictEqual(apples, oranges, `apples ${apples} !== oranges ${oranges}`);
// AssertionError [ERR_ASSERTION]: apples 1 !== oranges 2
assert.strictEqual(1, '1', new TypeError('Inputs are not identical'));
// TypeError: Inputs are not identical
其实断言这种东西日常开发中真的很少用到,不了解也不要紧,不会影响我们日常的工作开发,了解他可以让我们写出一些更加优雅的代码,当然这些代码也仅限于NodeJS,常规的Web开发中如果引入断言也可能成为一种负担。
[参考文献] (nodejs.org/dist/latest…)