本文大部分内容和 Node.js v8.9.0 文档内容相同,小部分加入了自己的理解和函数实例,是理解、重写而不是抄袭。
assert 模块提供了断言测试的函数,用于测试。一般测试模块都是对这个模块的封装。
此模块中只有函数,没有类。
如果测试失败,会抛出 AssertionError 类型的异常。
assert(value[, message])
assert.ok()的省略写法。
assert.deepEqual(actual, expected[, message])
测试 actual 和 expected 是否深度相等。对于原始值(比如数字、字符串、布尔值等)用相等运算符(==)比较。
只测试可枚举的自身属性,不测试对象的原型、连接符、或不可枚举的属性。也就是说和用 for 循环,然后用 hasOwnProperty 来测试 actual 和 expected 一样。
如果要测试原型,用 deepStrictEqual
如果提供了参数 message,就会用来替换默认的错误信息。
注意:两个没有自身属性的对象,比如 /a/gi 和 new Date() ,因为不是原始值,不会用相等比较,又因为是对象却没有自身属性,所以用自身属性比较的时候没有不等的,所以结果是不会抛出 AssertionError 。
另外,子对象中可枚举的自身属性也会被测试。
如果两个值不相等,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则赋予默认的错误信息。
assert.deepStrictEqual(actual, expected[, message])
原始值使用全等运算符比较, 对象的原型也使用全等运算符比较,对象的类型标签要求相同,包装对象会同时比较对象和拆箱值(原始值)。
类型标签要相同的意思是即使强行把一个对象的原型改为另一个不同类型对象的,比较的时候也不会认为是相同的。比如 var date = new Date(); var fakeDate = {}; Object.setPrototypeOf(fakeDate, Date.prototype); 这样一来 date 和 fakeDate 是具有相同原型链的对象,但是他们的类型标签(type tags)不同,所以也是会抛出错误的。
assert.doesNotThrow(block[, error][, message])
断言 block 函数不会抛出错误。
这个函数的意思就是说 block 这个函数不会抛出 error 那个类型的异常,其中 error 的类型可以是任何的异常类型,比如 TypeError, SyntaxError, ..., 等等。
message 同上,是附加在抛出的 AssertionError 的信息后面的。
assert.doesNotThrow( () => { throw new TypeError('错误信息'); }, TypeError, '抛出错误' ); // 抛出 AssertionError: Got unwanted exception (TypeError). 抛出错误
assert.equal(actual, expected[, message])
使用相等运算符(==)判断 actual 与 expect 是否相等, 不相等的话抛出 AssertionError
assert.fail(message)
assert.fail(actual, expected[, message[, operator[, stackStartFuncton]]])
operator 默认值为 '!='
如果只有 message 参数,相当于是一个抛出 AssertionError 的快捷方式,message 会作为 AssertionError 的详细信息。
如果 message 参数为空,则错误信息为 actual 参数 + operator 参数 + expected 参数。
如果提供了 stackStartFunction 参数,则该函数上的栈帧都会从栈信息中移除(详见 Error.captureStackTrace)。这句话的意思是 stackStartFunction 这个函数会从异常的栈信息中被移除,这样的会回溯的时候不会意识到函数执行过程中执行了这些。
var assert = require('assert'); function s() { a(); } function a() { b(); } function b() { assert.fail('a', 'b', undefined, '!=='); } s();
这次执行的结果是:
E:LSW s>node assert.js assert.js:60 throw new errors.AssertionError({ ^ AssertionError [ERR_ASSERTION]: 'a' !== 'b' at b (E:LSW sassert.js:12:12) at a (E:LSW sassert.js:8:5) at s (E:LSW sassert.js:4:5) at Object.<anonymous> (E:LSW sassert.js:15:1) at Module._compile (module.js:569:30) at Object.Module._extensions..js (module.js:580:10) at Module.load (module.js:503:32) at tryModuleLoad (module.js:466:12) at Function.Module._load (module.js:458:3) at Function.Module.runMain (module.js:605:10)
但是如果改为
function b() { assert.fail('a', 'b', undefined, '!==', a); }
执行结果就会变成
E:LSW s>node assert.js assert.js:60 throw new errors.AssertionError({ ^ AssertionError [ERR_ASSERTION]: 'a' !== 'b' at s (E:LSW sassert.js:4:5) at Object.<anonymous> (E:LSW sassert.js:15:1) at Module._compile (module.js:569:30) at Object.Module._extensions..js (module.js:580:10) at Module.load (module.js:503:32) at tryModuleLoad (module.js:466:12) at Function.Module._load (module.js:458:3) at Function.Module.runMain (module.js:605:10) at startup (bootstrap_node.js:158:16) at bootstrap_node.js:575:3
可见并不只是该函数的栈帧从栈信息中移除,而是该函数以上的栈帧都会从栈信息中移除。
assert.ifError(value)
判断 value 是否为假,否则抛出 value
try { assert.ifError(1); } catch (e) { console.log(e); }
这里的 e 就是 1
assert.notDeepEqual(actual, expected[, message])
如果不是 deepEqual 的话就不抛出异常,也就是说如果 actual 和 expected 不是深度相等的话,就能测试通过不抛异常。如果 deepEqual 的话反而会抛出异常。
assert.notDeepStrictEqual(actual, expected[, message])
测试 actual 与 expected 是否不深度全等。与 assert.deepStrictEqual() 相反。
assert.notEqual(actual, expected[, message])
使用不等运算符(!=)判断两个参数是否不相等。
assert.notStrictEqual(actual, expected[, message])
使用不全等运算符(!==)判断是否不是全等。
assert.ok(value[, message])
测试 value 是否为真值。相当于 assert.equal(!!value, true, message)
assert.strictEqual(actual, expected[, message])
使用全等运算符(===)判断是否全等。
assert.throws(block[, error][, message])
断言 block 函数会抛出错误。
error 参数可以是构造函数(比如 Error)、正则表达式(比如/错误/)、或自定义函数。
如果函数 block 抛出的异常和 error 不是同一种类型或者不是Error的子类的、或者不能匹配 error 正则表达式、或者自定义函数返回值为 false,那么就会抛出异常,否则就可以正常执行。
assert.throws( () => { throw new Error('错误信息'); }, SyntaxError );
会抛出异常。但是如果 Error 和 SyntaxError 反过来就不会抛出异常。
如果函数 block 抛出了异常,没有 error 参数或者 error 参数能够匹配抛出的异常,那么这个函数就能正常执行,否则就不能正常执行。如果 errro 参数的位置是一个字符串,那么不会被认定为是 error 参数,而是会被认定为 message 参数,真正的 message 参数会被忽略,实际上这时的 error 参数应该是正则形式的。
注意事项: 对于正负0的判断,或者 NaN === NaN 的判断,应该使用 Object.is()
因为
(0 === -1) = true
而
(NaN === NaN) = false