node.js学习之断言assert的使用示例


Posted in Javascript onSeptember 28, 2017

一. 简介

断言是编程术语,表示为一些布尔表达式,程序员相信在程序中的某个特定点该表达式值为真,可以在任何时候启用和禁用断言验证,因此可以在测试时启用断言而在部署时禁用断言。同样,程序投入运行后,最终用户在遇到问题时可以重新启用断言。

使用断言可以创建更稳定、品质更好且 不易于出错的代码。当需要在一个值为FALSE时中断当前操作的话,可以使用断言。【单元测试】必须使用断言。

Node提供了 10 多个断言测试的函数,用于测试不变式,我在文章中中将这 10 多个函数进行了分组,方便理解记忆。

【提示】在本文章中,expected 代表预期值,actual 代表实际值, message 代表自定义信息

二. 判断值是否为真值

判断值是否为真值有以下两个断言测试函数

2.1 assert(value[, message])

这个测试函数在 【Boolean(value)】 为 【true】时通过断言测试,否则抛出 【AssertionError】

const assert = require("assert");

assert("blue","第一个值为false时以我为错误信息抛出");

assert(true,"第一个值为false时以我为错误信息抛出");

上面一段代码由于【Boolean(value)】全部为 true,所以全部通过断言测试

assert(false,"第一个值为false时以我为错误信息抛出");

// AssertionError [ERR_ASSERTION]: 第一个值为false时以我为错误信息抛出

上面代码中 value 为false,则抛出一个带有 message 属性的 【AssertionError】,其中 message 属性的值等于传入的 message 参数的值。 【如果 message 参数为 undefined,则赋予默认的错误信息】。

assert(false);
// AssertionError [ERR_ASSERTION]: false == true

上面代码由于没有指定【message】参数,抛出的为默认错误信息的【AssertionError】

2.2 assert.ok(value[, message])

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】

3.1 assert.equal(actual, expected[, message])

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);
// 断言通过

上面代码由于比较的是同一个对象,两个值得引用相等,所以断言通过。

3.2 assert.deepEqual(actual, expected[, message])

同样也是测试 预期值 和 实际值 是否相等,使用的仍然是(==),但是与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()不测试对象的不可枚举的属性】

四. 判断预期值和实际值全等(===)

这组测试函数是用于判断预期值和实际值是否深度相等的,内部使用的是(===),所以对象的原型也会进行比较,值得类型也是比较的范围。这组也有两个测试函数。

4.1 assert.deepStrictEqual(actual, expected[, message])

由于内部使用的是全等(===),所以对象的原型也会计入比较的范围

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()将原型对象列入了比较对象】

4.2 assert.strictEqual(actual, expected[, message])

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()】断言测试

五. 判断预期值和实际值不相等(!=)

上面总结到了判断预期值和实际值相等,这儿总结一下判断预期值和实际值不想等的两个测试函数,实际上就是上面 (三) 的逆运算。

5.1 assert.notEqual(actual, expected[, message])

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() 】对于两个对象的测试通过是一个【恒成立】的结果。

5.2 assert.notDeepEqual(actual, expected[, message])

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时是永远否可以通过断言测试的。

六. 判断预期值和实际值严格不相等(!==)

上面总结到了判断预期值和实际值严格相等,这儿总结一下判断预期值和实际值严格不相等的两个测试函数,实际上就是上面 (四) 的逆运算

6.1 assert.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.2 assert.notDeepStrictEqual(actual, expected[, message])

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' }

七. 断言错误并抛出

这一组有 四 个(可以说是 三 个)测试函数,是对错误进行的处理。

7.1 assert.fail(message)

这个测试函数不多说,可以看错是下一个函数的重载,用于主动抛出带有【message】属性的【AssertionError】对象

assert.fail("自定义错误信息");
// AssertionError [ERR_ASSERTION]: 自定义错误信息

7.2 assert.fail(actual, expected[, message[, operator[, stackStartFunction]]])

该测试函数用于主动抛出自定义错误信息,抛出错误信息格式:【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

7.3 assert.throws(block,error, message)

参数说明:

block | Function

error | RegExp | Function

message | any

【说明!!】如果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;
  }
 },
 '不是期望的错误'
);

7.4 assert.doesNotThrow(block, error, message)

【说明!!】预期的错误和实际的错误一致时,不抛出实际错误,抛出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 的信息中

八. 判断值是否为真

这儿只有一个测试函数了

8.1 assert.ifError(value)

如果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 参数。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
Javascript & DHTML 实例编程(教程)(三)初级实例篇1—上传文件控件实例
Jun 02 Javascript
setTimeout和setInterval的区别你真的了解吗?
Mar 31 Javascript
jquery Tab效果和动态加载的简单实例
Dec 11 Javascript
bootstrap+jQuery实现的动态进度条功能示例
May 25 jQuery
Node.js学习之TCP/IP数据通讯(实例讲解)
Oct 11 Javascript
关于react-router/react-router-dom v4 history不能访问问题的解决
Jan 08 Javascript
6行代码实现微信小程序页面返回顶部效果
Dec 28 Javascript
js基础之事件捕获与冒泡原理
Oct 09 Javascript
使用webpack/gulp构建TypeScript项目的方法示例
Dec 18 Javascript
Vue-CLI与Vuex使用方法实例分析
Jan 06 Javascript
jQuery 判断元素是否存在然后按需加载内容的实现代码
Jan 16 jQuery
js实现鼠标点击飘爱心效果
Aug 19 Javascript
vue-router+vuex addRoutes实现路由动态加载及菜单动态加载
Sep 28 #Javascript
node.js学习之事件模块Events的使用示例
Sep 28 #Javascript
es6中的解构赋值、扩展运算符和rest参数使用详解
Sep 28 #Javascript
JS获取日期的方法实例【昨天,今天,明天,前n天,后n天的日期】
Sep 28 #Javascript
jquery实现左右轮播图效果
Sep 28 #jQuery
bootstrap table实现点击翻页功能 可记录上下页选中的行
Sep 28 #Javascript
JavaScript判断输入是否为数字类型的方法总结
Sep 28 #Javascript
You might like
PHP 抓取新浪读书频道的小说并生成txt电子书的代码
2009/12/18 PHP
PHP操作数组的一些函数整理介绍
2011/07/17 PHP
一个完整的php文件上传类实例讲解
2015/10/27 PHP
PHP实现图片防盗链破解操作示例【解决图片防盗链问题/反向代理】
2020/05/29 PHP
Jquery实现鼠标移上弹出提示框、移出消失思路及代码
2013/05/19 Javascript
js实现select跳转功能代码
2014/10/22 Javascript
jQuery实现Meizu魅族官方网站的导航菜单效果
2015/09/14 Javascript
js数组常见操作及数组与字符串相互转化实例详解
2015/11/10 Javascript
JavaScript 不支持 indexof 该如何解决
2016/03/30 Javascript
用自定义图片代替原生checkbox实现全选,删除以及提交的方法
2016/10/18 Javascript
JavaScript正则表达式小结(test|match|search|replace|split|exec)
2016/12/08 Javascript
JS常见简单正则表达式验证功能小结【手机,地址,企业税号,金额,身份证等】
2017/01/22 Javascript
JavaScript实现body内任意节点的自定义属性功能示例
2017/09/18 Javascript
浅谈vue中使用图片懒加载vue-lazyload插件详细指南
2017/10/23 Javascript
vue的.vue文件是怎么run起来的(vue-loader)
2018/12/10 Javascript
4 种滚动吸顶实现方式的比较
2019/04/09 Javascript
vue vantUI tab切换时 list组件不触发load事件的问题及解决方法
2020/02/14 Javascript
js实现移动端图片滑块验证功能
2020/09/29 Javascript
关于vue 项目中浏览器跨域的配置问题
2020/11/10 Javascript
[45:16]完美世界DOTA2联赛PWL S3 Magma vs Phoenix 第一场 12.12
2020/12/16 DOTA
Python随机生成数模块random使用实例
2015/04/13 Python
Python使用自带的ConfigParser模块读写ini配置文件
2016/06/26 Python
Windows下的Jupyter Notebook 安装与自定义启动(图文详解)
2018/02/21 Python
Python tkinter和exe打包的方法
2020/02/05 Python
通过HTML5 Canvas API绘制弧线和圆形的教程
2016/03/14 HTML / CSS
携程旅行网:中国领先的在线旅行服务公司
2017/02/17 全球购物
三个Unix的命令面试题
2015/04/12 面试题
书法比赛获奖感言
2014/02/10 职场文书
师德模范事迹材料
2014/06/03 职场文书
团队口号大全
2014/06/06 职场文书
导游词范文
2015/02/13 职场文书
护士自荐信范文
2015/03/25 职场文书
民事二审代理词
2015/05/25 职场文书
郭明义观后感
2015/06/08 职场文书
90行Python代码开发个人云盘应用
2021/04/20 Python
html css3不拉伸图片显示效果
2021/06/07 HTML / CSS