断言是编程术语,表示为一些布尔表达式,程序员相信在程序中的某个特定点该表达式值为真,能够在任什么时候候启用和禁用断言验证,所以能够在测试时启用断言而在部署时禁用断言。一样,程序投入运行后,最终用户在遇到问题时能够从新启用断言。程序员
使用断言能够建立更稳定、品质更好且 不易于出错的代码。当须要在一个值为FALSE时中断当前操做的话,可使用断言。【单元测试】必须使用断言。正则表达式
Node提供了 10 多个断言测试的函数,用于测试不变式,我在文章中将这 10 多个函数进行了分组,方便理解记忆。编程
【提示】在本文章中,expected 表明预期值,actual 表明实际值, message 表明自定义信息函数
判断值是否为真值有如下两个断言测试函数单元测试
这个测试函数在 【Boolean(value)】 为 【true】时经过断言测试,不然抛出 【AssertionError】测试
const assert = require("assert"); assert("blue","第一个值为false时以我为错误信息抛出"); assert(true,"第一个值为false时以我为错误信息抛出");
上面一段代码因为【Boolean(value)】所有为 true,因此所有经过断言测试ui
assert(false,"第一个值为false时以我为错误信息抛出"); // AssertionError [ERR_ASSERTION]: 第一个值为false时以我为错误信息抛出
上面代码中 value 为false,则抛出一个带有 message 属性的 【AssertionError】,其中 message 属性的值等于传入的 message 参数的值。 【若是 message 参数为 undefined,则赋予默认的错误信息】。.net
assert(false); // AssertionError [ERR_ASSERTION]: false == true
上面代码因为没有指定【message】参数,抛出的为默认错误信息的【AssertionError】code
assert.ok() 与 assert()的做用是同样的,都是测试【value】是否为真值。并且用法也同样,因此能够将assert()视为assert.ok()的语法糖对象
const assert = require("assert"); assert.ok(true); assert.ok(1);
上面代码【Boolean(value)】所有为 true,因此所有断言经过,下面是断言不经过的状况,分别列出了默认错误信息
assert.ok(0); //AssertionError [ERR_ASSERTION]: 0 == true assert.ok(false); //AssertionError [ERR_ASSERTION]: false == true assert.ok(false,"自定义错误信息"); //AssertionError [ERR_ASSERTION]: 自定义错误信息
这一组里面有两个测试函数,用于测试预期值与实际值是否相等,若是相等则断言经过,不然抛出 【AssertionError】
assert.equal()用于测试指望值和实际值是否相等,【在值类型的时候比较的是两个值是否相等,当预期值和实际值为引用类型的时候,比较的是值得引用】
assert.equal(1, 1); assert.equal("1", 1);
上面代码是对值类型进行的比较,说明equal()在内部使用的是(==),而非严格相等,待会儿我会总结到严格相等(===)
assert.equal({},{},"AssertionError"); assert.equal(() => { }, () => { }, "AssertionError"); assert.equal([],[],'AssertionError');
上面三个表达式都会抛出【message】属性值为'AssertionError'的【AssertionError】对象,【因此当值为引用类型的时候,equal()比较的是值得引用,所以两个引用类型的值是无法经过equal()断言的】
const obj={}; assert.equal(obj,obj); // 断言经过
上面代码因为比较的是同一个对象,两个值得引用相等,因此断言经过。
一样也是测试 预期值 和 实际值 是否相等,使用的仍然是(==),可是与equal不一样的是,【deepEqual()在对引用类型进行比较的时候,不是对值的引用进行比较,而是比较的对象的属性值】
const a = 'Blue', b = 'Pink'; assert.deepEqual(a,a,'actual unequal to expected'); // 断言经过 assert.deepEqual(a,b,'actual unequal to expected'); // AssertionError [ERR_ASSERTION]: actual unequal to expected
上面是对值类型进行的比较,和equal()没有任何的区别
const obj1 = { name: "foo", gender: "men" }, obj2 = { name: "foo", gender: "men" }, obj3 = { name: "bar", gender: "men" } assert.deepEqual(obj1, obj2, 'actual unequal to expected'); // 断言经过 assert.deepEqual(obj1, obj3, 'actual unequal to expected'); // AssertionError [ERR_ASSERTION]: actual unequal to expected
上面代码是对引用类型的比较,能够看出【deepEqual()】比较的是属性值,而非引用,这是与equal()不一样的地方。
【注意!!】deepEqual()只测试可枚举的自身属性,不测试对象的原型、链接符、或不可枚举的属性(这些状况使用 assert.deepStrictEqual(),稍后会总结到)
const son1 = Object.create(obj1), son2 = Object.create(obj2); son1.name="Summer"; son2.name="Summer"; assert.deepEqual(son1,son2,"actual unequal to expected"); // 断言经过
上面代码中 son1 和 son2 分别继承与两个不一样的对象,都拥有 name 为 “Summer” 的属性,最后的的结果是经过,说明【deepEqual()不测试对象的原型】
const ena = {}, enb = {}; Object.defineProperties(ena,{ name:{ value:"Blue" }, hobby:{ value:"foo", enumerable:false //可枚举性设置为false } }); Object.defineProperties(enb,{ name:{ value:"Blue" }, hobby:{ value:"bar", enumerable:false //可枚举性设置为false } }) assert.deepEqual(ena,enb,"actual unequal to expected") //ok,actual equal to expected
上面代码中 ena 和 enb 用于相同的可枚举属性【name】,有着值不一样的不可枚举属性【hobby】,说明【deepEqual()不测试对象的不可枚举的属性】
这组测试函数是用于判断预期值和实际值是否深度相等的,内部使用的是(===),因此对象的原型也会进行比较,值得类型也是比较的范围。这组也有两个测试函数。
因为内部使用的是全等(===),因此对象的原型也会计入比较的范围
const obj1 = { name: "foo", gender: "men" }, obj2 = { name: "bar", gender: "men" } const son1 = Object.create(obj1), son2 = Object.create(obj2); son1.name = "Summer"; son2.name = "Summer"; assert.deepEqual(son1, son2, "actual unequal to expected"); //断言经过 assert.deepStrictEqual(son1, son2, "actual unequal to expected") //AssertionError [ERR_ASSERTION]: actual unequal to expected
上面代码使用了deepEqual()和deepStrictEqual()进行了断言测试,son1 和 son2 分别继承与两个不一样的对象,可是拥有相同的属性值。能够看出【deepEqual()是不会考虑对象的原型的,deepStrictEqual()将原型对象列入了比较对象】
strictEqual()是equal()的增强,考虑了数据类型;若是actual === expected,则断言经过,不然抛出AssertionError,message?message:默认错误信息。
assert.strictEqual(1, 2); // 抛出 AssertionError: 1 === 2 assert.strictEqual(1, 1); // 测试经过。 assert.strictEqual(1, '1'); // 抛出 AssertionError: 1 === '1' assert.equal(1, '1'); // 测试经过。
【提示!!】对引用类型仍是永远通不过【strictEqual()】断言测试
上面总结到了判断预期值和实际值相等,这儿总结一下判断预期值和实际值不想等的两个测试函数,实际上就是上面 (三) 的逆运算。
【notEqual()】为 【equal()】的逆运算,若是 actual!= expected 则断言经过,一样对于值类型是单纯对值进行比较,对应引用类型比较的是值得引用
assert.notEqual("1", "2"); // 断言经过 assert.notEqual("1", 2); // 断言经过 assert.notEqual("1", 1); // AssertionError [ERR_ASSERTION]: '1' != 1
上面代码是对值类型进行的比较,第三个表达式的默认信息能够看出内部使用的是(!=)
assert.notEqual({ a: "foo" }, { a: "foo" }); assert.notEqual(() => { }, () => { }); assert.notEqual([], []);
上面的代码是对引用类型进行的断言测试,【notEqual()】对于两个对象的测试经过是一个【恒成立】的结果。
【notDeepEqual()】为 【deepEqual()】的逆运算,若是 actual!= expected 则断言经过,不一样于notEqual()的是对于引用类型是对值进行判断,不比对原型、不可枚举属性,只比对自有可枚举属性,断言经过。
const obj1 = { a: "foo" }, obj2 = { b: "bar" }, obj3 = Object.create(obj1); assert.notDeepEqual(obj1,obj1,'actual equal to expected'); // AssertionError [ERR_ASSERTION]: actual equal to expected assert.notDeepEqual(obj1,obj2,'actual equal to expected'); // 断言经过 assert.notDeepEqual(obj1,obj3,'actual equal to expected'); // 断言经过
上面代码中最后一个表达式断言经过,说明【不比对原型、不可枚举属性,只比对自有可枚举属性】
【注意!!】与notEqual的区别,也就是deepEqual和equal的区别,在引用数据类型的时候,deepEqual是比较的值而非引用,equal对比的是引用,因此引用类型在equal的时候是永远没法经过断言测试的,以此类推,引用类型在notEqual时是永远否能够经过断言测试的。
上面总结到了判断预期值和实际值严格相等,这儿总结一下判断预期值和实际值严格不相等的两个测试函数,实际上就是上面 (四) 的逆运算。
若是actual与expected不 !== 则断言经过, 与 assert.deepStrictEqual() 相反
assert.notStrictEqual("1", 1); // 断言经过 assert.notStrictEqual("1", "1"); // AssertionError [ERR_ASSERTION]: '1' !== '1'
上面代码是对值类型进行的断言测试,能够看出【notStrictEqual()】考虑了数据类型
assert.notStrictEqual({ a: "foo" }, { a: "foo" }); assert.notStrictEqual(() => { }, () => { }); assert.notStrictEqual([], []);
上面代码是对引用类型的测试,所有经过,以上表达式是恒经过的。
notDeepStrictEqual()就是deepStrictEqual()的逆运算,若是 actual !== expected 则断言经过,不然抛出AssertionError。
assert.notDeepStrictEqual({ a: '1' }, { a: 1 }); //断言经过 assert.notDeepStrictEqual({ a: '1' }, { a: "1" }); //AssertionError [ERR_ASSERTION]: { a: '1' } notDeepStrictEqual { a: '1' }
这一组有 四 个(能够说是 三 个)测试函数,是对错误进行的处理。
这个测试函数很少说,能够看错是下一个函数的重载,用于主动抛出带有【message】属性的【AssertionError】对象
assert.fail("自定义错误信息"); // AssertionError [ERR_ASSERTION]: 自定义错误信息
该测试函数用于主动抛出自定义错误信息,抛出错误信息格式:【actual 参数 + operator 参数 + expected 参数】
assert.fail("BLUE","PINK"); // AssertionError [ERR_ASSERTION]: 'BLUE' != 'PINK'
上面代码不提供【message】和【operator】,则【operator】默认为 【!=】
assert.fail("BLUE","PINK","自定义的错误信息"); // AssertionError [ERR_ASSERTION]: 自定义的错误信息 assert.fail("BLUE","PINK","自定义的错误信息","?",()=>{ console.log("hello"); }); // AssertionError [ERR_ASSERTION]: 自定义的错误信息
上面代码提供【message】,这时候 【actual】、【operator】、【expected】等参数会被列入错误对象属性中
assert.fail("BLUE","PINK",undefined); // AssertionError [ERR_ASSERTION]: 'BLUE' undefined 'PINK' assert.fail("BLUE","PINK",undefined,"?"); // AssertionError [ERR_ASSERTION]: 'BLUE' ? 'PINK'
上面代码是【message】为 undefined 时,会检测【operator】参数,【operator?operator:undefined 】
参数说明:
【说明!!】若是block抛出的错误知足error参数,也就是抛出错误与指望一致,则断言经过,不然抛出block中的错误,若是block不抛出错误,则抛出【AssertionError 】。
【提示!!】error 参数能够是构造函数、正则表达式、或自定义函数。
assert.throws( () => { throw new Error('错误信息'); }, Error );
上面代码中 error 参数为构造函数,【block】抛出的错误与预期的一致,因此断言经过。
assert.throws( () => { throw new Error('错误信息'); }, /错误/ );
上面代码中 error 参数为正则表达式,【block】抛出的错误知足正则表达式,因此断言经过。
【注意!!】error 参数不能是字符串。 若是第二个参数是字符串,则视为省略 error 参数,传入的字符串会被用于 【message】 参数,
// 这是错误的!不要这么作! assert.throws(myFunction, '错误信息', '没有抛出指望的信息'); // 应该这么作。 assert.throws(myFunction, /错误信息/, '没有抛出指望的信息');
下面代码,【error】 参数为自定义函数
assert.throws( () => { throw new Error('错误信息'); }, function (err) { if ((err instanceof Error) && /错误/.test(err)) { return true; } }, '不是指望的错误' );
【说明!!】预期的错误和实际的错误一致时,不抛出实际错误,抛出AssertionError,不一致则抛出实际错误信息
assert.doesNotThrow( () => { throw new TypeError('错误信息'); }, SyntaxError );
以上例子会抛出 TypeError,由于在断言中没有匹配的错误类型
assert.doesNotThrow( () => { throw new TypeError('错误信息'); }, TypeError );
以上例子会抛出一个带有 Got unwanted exception (TypeError).. 信息的 AssertionError
assert.doesNotThrow( () => { throw new TypeError('错误信息'); }, TypeError, '抛出错误' ); // 抛出 AssertionError: Got unwanted exception (TypeError). 抛出错误
上面代码说明:若是抛出了 AssertionError 且有给 message 参数传值,则 message 参数的值会被附加到 AssertionError 的信息中
这儿只有一个测试函数了
若是value的值为真或者能够转换成true,则抛出value,不然断言经过。
assert.ifError(true); //抛出true assert.ifError(false); //断言经过
上面代码中是直接给出的 布尔 类型的值,若是值为 true 则会将该值抛出,不然什么也不作
assert.ifError(0); //断言经过 assert.ifError("0"); //抛出 "0" assert.ifError(1); //抛出 1 assert.ifError(new Error()); //抛出 Error,对象名称
上面代码中所有是经过 Boolean(value) 转换以后再进行的测试,利用这个特性咱们能够将此测试函数用于测试回调函数的 error 参数。
--------------------------END--------------------------
CSDN【Node断言assert】同步更新