node Assertion 断言
断言模式
node 的断言分为严格模式和非严格模式,这两者在应用和 log 展现上有不同之处(略)
集体举荐应用严格模式,信息展现更加清晰
引入形式:
// 严格模式
const assert = require('assert').strict;
// 非严格模式
const assert = require('assert');
抛出谬误(Class: assert.AssertionError)
继承于<errors.Error>
— 参数
message
[<string>]actual
[<any>]expected
[<any>]operator
[<string>]stackStartFn
[<Function>]
method
办法分为 3 类
一、单个值的断言
assert(value[, message])
===assert.ok(value[, message])
// 是 truthy 时通过assert.doseNotMatch(String,regexp[,message])
// 正则不匹配字符串时通过assert.match(string, regexp[, message])
// 正则匹配字符串时通过assert.ifError(value)
// 是null
或者undefined
时通过
留神点:
- doseNotMatch 和 match 的匹配值必须是 String(感觉很弱);
- ifError 的值不是判断 falsly 值;
二、两个值的断言
assert.deepStrictEqual(actual, expected[, message])
// 合乎 SameValue Comparison 准则,援用类型可比拟assert.notDeepStrictEqual(actual, expected[, message])
// 合乎 SameValue Comparison 准则,援用类型可比拟assert.strictEqual(actual, expected[, message])
// 合乎 SameValue Comparison 准则,援用类型不可比拟assert.notStrictEqual(actual, expected[, message])
// 合乎 SameValue Comparison 准则,援用类型不可比拟
留神点:
- 不可比拟的意思是必须是同一个援用地址才雷同,比拟不同援用类型时报错;
- 比拟的办法在最初面;
- 参数别离是理论值,期望值,当产生谬误时的 message|error;
三、对函数的断言
assert.rejects(asyncFn[, error][, message])
// 异步函数断言,当 reject 没有产生时触发assert.throws(fn[, error][, message])
// 同步函数断言,当函数没有抛出谬误时触发assert.doesNotReject(asyncFn[, error][, message])
// 异步函数断言,当 reject 触发assert.doesNotThrow(fn[, error][, message])
// 同步函数断言,抛出谬误时触发
留神点:
- 如果第二个参数传递,且是字符串,而且没有第三个参数的时候,会将第二个参数作为 message 的传参;
- 官网说前面两个断言的意义不大的起因,集体认为是因为当函数抛出谬误的时候断言也抛出谬误,与其在断言 assert 中解决这个谬误,不如间接在函数逻辑中解决更为间接;
- error 参数必须和函数抛出的谬误相匹配,也就是说判断抛出的谬误必须蕴含 error 参数,不然报错。能够想到这种断言能够断言两种状况,即是否产生断言,而产生断言后抛出的谬误是否与预期的 error 相匹配(当有嵌套的对象时,嵌套的对象构造必须是预期和理论一样能力通过);
// 以官网例子为准, 此时能通过
const err = new TypeError('谬误值');
err.code = 404;
err.foo = 'bar';
err.info = {
nested: true,
baz: 'text'
};
err.reg = /abc/i;
assert.throws(() => {throw err;}, {
name: 'TypeError',
message: '谬误值',
info: {
nested: true,
baz: 'text'
}
}
);
// 谬误, 因为断言的对象上不存在 a
const err = new TypeError('谬误值');
err.code = 404;
err.foo = 'bar';
err.info = {
nested: true,
baz: 'text'
};
err.reg = /abc/i;
assert.throws(() => {throw err;}, {
name: 'TypeError',
message: '谬误值',
info: {
nested: true,
baz: 'text'
},
a:1
}
);
// 正确,尽管断言上的属性没有 a,然而其余属性都能通过测验
const err = new TypeError('谬误值');
err.code = 404;
err.foo = 'bar';
err.a = 1
err.info = {
nested: true,
baz: 'text'
};
err.reg = /abc/i;
assert.throws(() => {throw err;}, {
name: 'TypeError',
message: '谬误值',
info: {
nested: true,
baz: 'text'
}
}
);
严格相等的规定
1. 根底类型的比拟应用 Object.is()
比拟;
2. 对象的类型标签 比方官网的例子中;
// 以下对象没有本身属性。const date = new Date();
const object = {};
const fakeDate = {};
Object.setPrototypeOf(fakeDate, Date.prototype);
// 留神,setPrototyOf 办法官网不举荐,我应用的 Object.create()代替 let fakeDate = Object.create(date)
// 类型标签不同:assert.deepStrictEqual(date, fakeDate);
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
// + 2018-04-26T00:49:08.604Z
// - Date {}
咋看之下 date 的原型链和 fakeDate 的是截然不同的,然而本质上一个是具体的工夫,而另外一个是 date 对象
3. 比拟原型
// 如上代码中,原型不同:assert.deepStrictEqual(object, fakeDate);
// AssertionError: Expected inputs to be strictly deep- equal:
// + actual - expected
//
// + {}
// - Date {}
4. 只思考可枚举的本身属性
这里记忆的时候能够把 Symbol 属性思考上
5. 特例Error
,因为须要比拟不可枚举属性names
和 messages
6. 对象封装器作为对象和解封装后的值都进行比拟
这里指的是 String()
、Number()
等等,因为实质上应用这些办法进行类型转换其实是将根底类型转成对象解决,不然在根底类型下面是不会有办法能够调用的,所以翻译成对象封装器(我感觉还行吧)。比拟的时候是比拟函数调用之后的后果,比方官网例子:
// 解封装后的数字不同:assert.deepStrictEqual(new Number(1), new Number(2));
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
// + [Number: 1]
// - [Number: 2]
assert.deepStrictEqual(new String('foo'), Object('foo'));
// 通过,因为对象与解封装后的字符串都是雷同的。
7.Object 的属性、Map 的键名和 Set 的子项,他们的比拟是无序比拟
8. 当两边的值不雷同或遇到循环援用时,递归进行。
这个的意思是当发现比拟的单方是不同的时候,比拟就进行,不会始终比拟到最初。而 node 发现比拟过程中存在循环援用的时候就进行比拟(报错信息临时不晓得)
9.WeakMap 和 WeakSet 的比拟不依赖于它们的值。
WeakMap 和 WeakSet 的外在键值对是无奈比拟的,因为是弱援用,所以当比拟的时候兴许有值兴许没有,所以当两个 WeakMap 比拟的时候默认是能够相等的,然而当 WeakMap 强行增加一个强援用的键值对,就必须要求同样的 WeakMap 具备这个强援用的键值对。
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);
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
// WeakMap {// + [items unknown]
// - [items unknown],
// - unequal: true
// }