1.简介断言是一个编程术语,表示为一些布尔表达式,程序员认为在程序的某一点表达式的值是真的,可以随时启用和禁用断言验证,因此可以为测试启用断言,为部署禁用断言。同样,在程序上线后,如果最终用户遇到问题,他们可以重新启用断言。使用断言可以创建更稳定、质量更好且不易出错的代码。当一个值为FALSE时需要中断当前操作时,可以使用断言。[单元测试]必须使用断言。Node提供了10多个断言测试函数来测试不变量。为了便于理解和记忆,我将这10多个函数归类在了文章中。【提示】本文expected表示期望值,actual表示实际值,message表示自定义信息2.判断value是否为真有两个断言测试函数如下2.1assert(value[,message])这个测试函数在[Boolean(value)]为[true]时通过断言测试,否则抛出[AssertionError]constassert=require("assert");assert("blue","ThefirstvalueisWhenitisfalse,错误信息随我抛出");assert(true,"当第一个值为false时,错误信息随我抛出");上面的代码都是真的,因为[Boolean(value)]都是通过断言测试assert(false,"当第一个值为false时,把我当成错误信息丢给我");//AssertionError[ERR_ASSERTION]:当第一个值为false时,将我作为上面代码中的错误信息值抛出如果为false,则会抛出一个带有message属性的[AssertionError],其中message属性的值为等于传入消息参数的值。[如果未定义消息参数,将分配默认错误消息]。assert(false);//AssertionError[ERR_ASSERTION]:false==true由于上面代码没有指定[message]参数,所以抛出的是默认的错误信息[AssertionError]2.2assert.ok(value[,message])断言。ok()和assert()的功能一样,都是测试[value]是否为真。并且用法相同,所以assert()可以看作是assert.ok()的语法糖constassert=require("assert");assert.ok(true);assert.ok(1);上面的代码[Boolean(value)]都是真的,所以所有的断言都通过了。下面是断言失败的情况,分别列出默认的错误信息assert.ok(0);//AssertionError[ERR_ASSERTION]:0==trueassert.ok(false);//AssertionError[ERR_ASSERTION]:false==trueassert.ok(false,"customerrormessage");//AssertionError[ERR_ASSERTION]:customerrormessage3.判断期望值等于实际值(==)这个有两个测试函数合二为一组,用于检验期望值是否等于实际值。如果它们相等,则断言通过,否则[AssertionError]被抛出。3.1assert.equal(actual,expected[,message])assert.equal()用于测试期望值和实际值是否相等。【值类型比较两个值是否相等时,期望值和实际值是引用类型时比较值得参考】assert.equal(1,1);assert.equal("1",1);上面的代码是对值类型的比较,说明equal()内部使用的是(==),而不是严格相等。后面会总结严格相等equal(===)assert.equal({},{},"AssertionError");assert.equal(()=>{},()=>{},"AssertionError");assert.equal([],[],'AssertionError');以上三个表达式会抛出一个属性值为'AssertionError'[AssertionError]的[message]对象,[所以当值为引用类型时,equal()比较的是值得引用的值,所以两个值ofreferencetypescannotbeassertedthroughequal()]constobj={};assert.equal(obj,obj);//通过上面代码断言比较的是同一个对象,两个值领先使用相等,所以断言通过3.2assert.deepEqual(actual,expected[,message])也测试期望值和实际值是否相等,使用(==),但不同于equal,[deepEqual()比较时引用类型,比较的不是对值的引用,而是被比较对象的属性值]consta='Blue',b='Pink';assert.deepEqual(a,a,'actualunequaltoexpected');//assertthroughassert.deepEqual(a,b,'actualunequaltoexpected');//AssertionError[ERR_ASSERTION]:actualunequaltoexpected以上是值类型的比较,equal()确实没有任何区别constobj1={name:"foo",gender:"men"},obj2={name:"foo",gender:"men"},obj3={name:"bar",gender:"men"}assert.deepEqual(obj1,obj2,'actualunequaltoexpected');//Assertionpassedassert.deepEqual(obj1,obj3,'actualunequaltoexpected');//AssertionError[ERR_ASSERTION]:actualunequaltoexpected以上代码它是引用类型的比较。可以看出,[deepEqual()]比较的是属性值,而不是引用,这一点与equal()不同。【注意!!】deepEqual()只测试可枚举的自身属性,不测试对象的原型、连接器或不可枚举的属性(在这些情况下,使用assert.deepStrictEqual(),后面会总结)constson1=Object.create(obj1),son2=Object.create(obj2);son1.name="Summer";son2.name="Summer";assert.deepEqual(son1,son2,"actualunequaltoexpected");//上面通过的assert代码中,son1和son2分别继承了两个不同的对象,两者都有名为“Summer”的属性,最后结果通过,说明【deepEqual()没有测试对象的原型】constena={},enb={};Object.defineProperties(ena,{name:{value:"Blue"},hobby:{value:"foo",enumerable:false//enumerable设置为false}});Object.defineProperties(enb,{name:{value:"Blue"},hobby:{value:"bar",enumerable:false//setenumerabilitytofalse}})assert.deepEqual(ena,enb,"actualunequaltoexpected")//ok,actualequaltoexpected在上面的代码中,ena和enb用于同一个可枚举属性[name],具有不同取值的非可枚举属性[hobby],说明[deepEqual()不测试对象的不可枚举属性引用的属性]4.判断thattheexpectedvalueandactualvalueiscongruent(===)这组测试函数是用来深度判断期望值和实际值是否相等,内部使用的是(===),所以objectPrototypes也会被比较,valuetypes也会被scoped进行比较。该组还有两个测试函数。4.1assert.deepStrictEqual(actual,expected[,message])由于内部使用同余(===),所以对象的原型也会被纳入比较范围constobj1={name:"foo",gender:“男人”},obj2={名称:“酒吧”,性别:“男人”}constson1=Object.create(obj1),son2=Object.create(obj2);son1.name=“夏天”;son2.name="Summer";assert.deepEqual(son1,son2,"actualunequaltoexpected");//断言通过assert.deepStrictEqual(son1,son2,"actualunequaltoexpected")//AssertionError[ERR_ASSERTION]:actualunequalto上面预期的代码使用deepEqual()和deepStrictEqual()进行断言测试,son1和son2分别继承自两个不同的对象,但是具有相同的属性值。可以看出【deepEqual()没有考虑对象的原型,deepStrictEqual()包括原型对象作为比较对象】4.2assert.strictEqual(actual,expected[,message])strictEqual()是一个增强equal(),考虑数据类型;如果预期实际===,则断言通过,否则抛出AssertionError,消息?message:默认的错误信息。assert.strictEqual(1,2);//抛出AssertionError:1===2assert.strictEqual(1,1);//测试通过。assert.strictEqual(1,'1');//ThrowAssertionError:1==='1'assert.equal(1,'1');//测试通过。【暗示!!】引用类型永远不会通过【strictEqual()】断言测试5.判断期望值和实际值不相等(!=)以上总结了期望值和实际值相等的判断。这里总结一下判断期望值和实际值。两个测试函数等,其实就是上面(3)的逆运算。5.1assert.notEqual(actual,expected[,message])[notEqual()]是[equal()]的逆运算。如果actual!=expected,则断言通过。同样,对于值类型,只是比较值,对应的引用类型比较值得引用assert.notEqual("1","2");//Assertedviaassert.notEqual("1",2);//Assertedviaassert.notEqual("1",1);//AssertionError[ERR_ASSERTION]:'1'!=1上面的代码是比较值类型,第三个表达式的默认信息可以看出(!=)assert.notEqual({a:"foo"},{a:"foo"});assert.notEqual(()=>{},()=>{});assert.notEqual([],[]);上面的代码是针对引用类型[notEqual()]的断言测试是两个对象通过测试的[常量建立]的结果。5.2assert.notDeepEqual(actual,expected[,message])[notDeepEqual()]是[deepEqual()]的逆运算。如果actual!=expected,则断言通过。与notEqual()不同的是,它是对引用类型的值做判断,不比较原型和不可枚举属性,只比较自身的可枚举属性,断言通过。constobj1={a:"foo"},obj2={b:"bar"},obj3=Object.create(obj1);assert.notDeepEqual(obj1,obj1,'actualequaltoexpected');//AssertionError[ERR_ASSERTION]:actualequaltoexpectedassert.notDeepEqual(obj1,obj2,'actualequaltoexpected');//断言通过assert.notDeepEqual(obj1,obj3,'actualequaltoexpected');//断言结束时通过上面的代码一个表达式断言通过,说明【不比较原型,不可枚举属性,只比较自枚举属性】【注意!!】与notEqual的区别,即deepEqual和equal的区别,在引用数据类型时,deepEqual是比较值而不是引用,equal比较的是引用,所以引用类型永远不能通过相等时的断言测试等等,当引用类型不等于时,它永远无法通过断言测试。六。判断期望值和实际值严格不相等(!==)以上总结了期望值和实际值严格相等的判断。这里总结一下判断期望值和实际值严格不相等的两个测试函数。其实就是上面(4)的逆运算。6.1assert.notStrictEqual(actual,expected[,message])如果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([],[]);上面的代码是对引用类型的测试,全部通过,上面的表达式总是通过。6.2assert.notDeepStrictEqual(actual,expected[,message])notDeepStrictEqual()是deepStrictEqual()的逆运算,如果是的话!==预期,断言通过,否则抛出AssertionError。assert.notDeepStrictEqual({a:'1'},{a:1});//断言通过assert.notDeepStrictEqual({a:'1'},{a:"1"});//AssertionError[ERR_ASSERTION]:{a:'1'}notDeepStrictEqual{a:'1'}七。断言和抛出错误这组四个(可以说是三个)测试函数处理错误。7.1assert.fail(message)这个测试函数就不多说了,可以看成是对next函数的重载,用来主动抛出具有[message]属性的[AssertionError]对象assert.fail("customerrormessage");//AssertionError[ERR_ASSERTION]:Customerrormessage7.2assert.fail(actual,expected[,message[,operator[,stackStartFunction]]])该测试函数用于主动抛出自定义错误信息,throw错误信息格式:[实际参数+运算符参数+预期参数]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]isundefined当检测到[operator]参数时,[operator?operator:undefined]7.3assert.throws(block,error,message)参数说明:block
