node.js學(xué)習(xí)之?dāng)嘌詀ssert的使用示例
一. 簡(jiǎn)介
斷言是編程術(shù)語,表示為一些布爾表達(dá)式,程序員相信在程序中的某個(gè)特定點(diǎn)該表達(dá)式值為真,可以在任何時(shí)候啟用和禁用斷言驗(yàn)證,因此可以在測(cè)試時(shí)啟用斷言而在部署時(shí)禁用斷言。同樣,程序投入運(yùn)行后,最終用戶在遇到問題時(shí)可以重新啟用斷言。
使用斷言可以創(chuàng)建更穩(wěn)定、品質(zhì)更好且 不易于出錯(cuò)的代碼。當(dāng)需要在一個(gè)值為FALSE時(shí)中斷當(dāng)前操作的話,可以使用斷言?!締卧獪y(cè)試】必須使用斷言。
Node提供了 10 多個(gè)斷言測(cè)試的函數(shù),用于測(cè)試不變式,我在文章中中將這 10 多個(gè)函數(shù)進(jìn)行了分組,方便理解記憶。
【提示】在本文章中,expected 代表預(yù)期值,actual 代表實(shí)際值, message 代表自定義信息
二. 判斷值是否為真值
判斷值是否為真值有以下兩個(gè)斷言測(cè)試函數(shù)
2.1 assert(value[, message])
這個(gè)測(cè)試函數(shù)在 【Boolean(value)】 為 【true】時(shí)通過斷言測(cè)試,否則拋出 【AssertionError】
const assert = require("assert");
assert("blue","第一個(gè)值為false時(shí)以我為錯(cuò)誤信息拋出");
assert(true,"第一個(gè)值為false時(shí)以我為錯(cuò)誤信息拋出");
上面一段代碼由于【Boolean(value)】全部為 true,所以全部通過斷言測(cè)試
assert(false,"第一個(gè)值為false時(shí)以我為錯(cuò)誤信息拋出"); // AssertionError [ERR_ASSERTION]: 第一個(gè)值為false時(shí)以我為錯(cuò)誤信息拋出
上面代碼中 value 為false,則拋出一個(gè)帶有 message 屬性的 【AssertionError】,其中 message 屬性的值等于傳入的 message 參數(shù)的值。 【如果 message 參數(shù)為 undefined,則賦予默認(rèn)的錯(cuò)誤信息】。
assert(false); // AssertionError [ERR_ASSERTION]: false == true
上面代碼由于沒有指定【message】參數(shù),拋出的為默認(rèn)錯(cuò)誤信息的【AssertionError】
2.2 assert.ok(value[, message])
assert.ok() 與 assert()的作用是一樣的,都是測(cè)試【value】是否為真值。而且用法也一樣,所以可以將assert()視為assert.ok()的語法糖
const assert = require("assert");
assert.ok(true);
assert.ok(1);
上面代碼【Boolean(value)】全部為 true,所以全部斷言通過,下面是斷言不通過的情況,分別列出了默認(rèn)錯(cuò)誤信息
assert.ok(0); //AssertionError [ERR_ASSERTION]: 0 == true assert.ok(false); //AssertionError [ERR_ASSERTION]: false == true assert.ok(false,"自定義錯(cuò)誤信息"); //AssertionError [ERR_ASSERTION]: 自定義錯(cuò)誤信息
三. 判斷預(yù)期值和實(shí)際值相等(==)
這一組里面有兩個(gè)測(cè)試函數(shù),用于測(cè)試預(yù)期值與實(shí)際值是否相等,如果相等則斷言通過,否則拋出 【AssertionError】
3.1 assert.equal(actual, expected[, message])
assert.equal()用于測(cè)試期望值和實(shí)際值是否相等,【在值類型的時(shí)候比較的是兩個(gè)值是否相等,當(dāng)預(yù)期值和實(shí)際值為引用類型的時(shí)候,比較的是值得引用】
assert.equal(1, 1);
assert.equal("1", 1);
上面代碼是對(duì)值類型進(jìn)行的比較,說明equal()在內(nèi)部使用的是(==),而非嚴(yán)格相等,待會(huì)兒我會(huì)總結(jié)到嚴(yán)格相等(===)
assert.equal({},{},"AssertionError");
assert.equal(() => { }, () => { }, "AssertionError");
assert.equal([],[],'AssertionError');
上面三個(gè)表達(dá)式都會(huì)拋出【message】屬性值為'AssertionError'的【AssertionError】對(duì)象,【所以當(dāng)值為引用類型的時(shí)候,equal()比較的是值得引用,因此兩個(gè)引用類型的值是沒法通過equal()斷言的】
const obj={};
assert.equal(obj,obj);
// 斷言通過
上面代碼由于比較的是同一個(gè)對(duì)象,兩個(gè)值得引用相等,所以斷言通過。
3.2 assert.deepEqual(actual, expected[, message])
同樣也是測(cè)試 預(yù)期值 和 實(shí)際值 是否相等,使用的仍然是(==),但是與equal不同的是,【deepEqual()在對(duì)引用類型進(jìn)行比較的時(shí)候,不是對(duì)值的引用進(jìn)行比較,而是比較的對(duì)象的屬性值】
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
上面是對(duì)值類型進(jìn)行的比較,和equal()沒有任何的區(qū)別
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
上面代碼是對(duì)引用類型的比較,可以看出【deepEqual() 】比較的是屬性值,而非引用,這是與equal()不同的地方。
【注意?。 ?/strong>deepEqual()只測(cè)試可枚舉的自身屬性,不測(cè)試對(duì)象的原型、連接符、或不可枚舉的屬性(這些情況使用 assert.deepStrictEqual() ,稍后會(huì)總結(jié)到)
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 分別繼承與兩個(gè)不同的對(duì)象,都擁有 name 為 “Summer” 的屬性,最后的的結(jié)果是通過,說明【deepEqual()不測(cè)試對(duì)象的原型】
const ena = {}, enb = {};
Object.defineProperties(ena,{
name:{
value:"Blue"
},
hobby:{
value:"foo",
enumerable:false //可枚舉性設(shè)置為false
}
});
Object.defineProperties(enb,{
name:{
value:"Blue"
},
hobby:{
value:"bar",
enumerable:false //可枚舉性設(shè)置為false
}
})
assert.deepEqual(ena,enb,"actual unequal to expected")
//ok,actual equal to expected
上面代碼中 ena 和 enb 用于相同的可枚舉屬性【name】,有著值不同的不可枚舉屬性【hobby】,說明【deepEqual()不測(cè)試對(duì)象的不可枚舉的屬性】
四. 判斷預(yù)期值和實(shí)際值全等(===)
這組測(cè)試函數(shù)是用于判斷預(yù)期值和實(shí)際值是否深度相等的,內(nèi)部使用的是(===),所以對(duì)象的原型也會(huì)進(jìn)行比較,值得類型也是比較的范圍。這組也有兩個(gè)測(cè)試函數(shù)。
4.1 assert.deepStrictEqual(actual, expected[, message])
由于內(nèi)部使用的是全等(===),所以對(duì)象的原型也會(huì)計(jì)入比較的范圍
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()進(jìn)行了斷言測(cè)試,son1 和 son2 分別繼承與兩個(gè)不同的對(duì)象,但是擁有相同的屬性值??梢钥闯觥?code>deepEqual()是不會(huì)考慮對(duì)象的原型的,deepStrictEqual()將原型對(duì)象列入了比較對(duì)象】
4.2 assert.strictEqual(actual, expected[, message])
strictEqual()是equal()的加強(qiáng),考慮了數(shù)據(jù)類型;如果actual === expected,則斷言通過,否則拋出AssertionError,message?message:默認(rèn)錯(cuò)誤信息。
assert.strictEqual(1, 2); // 拋出 AssertionError: 1 === 2 assert.strictEqual(1, 1); // 測(cè)試通過。 assert.strictEqual(1, '1'); // 拋出 AssertionError: 1 === '1' assert.equal(1, '1'); // 測(cè)試通過。
【提示!!】對(duì)引用類型還是永遠(yuǎn)通不過【strictEqual()】斷言測(cè)試
五. 判斷預(yù)期值和實(shí)際值不相等(!=)
上面總結(jié)到了判斷預(yù)期值和實(shí)際值相等,這兒總結(jié)一下判斷預(yù)期值和實(shí)際值不想等的兩個(gè)測(cè)試函數(shù),實(shí)際上就是上面 (三) 的逆運(yùn)算。
5.1 assert.notEqual(actual, expected[, message])
【notEqual()】為 【equal() 】的逆運(yùn)算,如果 actual!= expected 則斷言通過,同樣對(duì)于值類型是單純對(duì)值進(jìn)行比較,對(duì)應(yīng)引用類型比較的是值得引用
assert.notEqual("1", "2");
// 斷言通過
assert.notEqual("1", 2);
// 斷言通過
assert.notEqual("1", 1);
// AssertionError [ERR_ASSERTION]: '1' != 1
上面代碼是對(duì)值類型進(jìn)行的比較,第三個(gè)表達(dá)式的默認(rèn)信息可以看出內(nèi)部使用的是(!=)
assert.notEqual({ a: "foo" }, { a: "foo" });
assert.notEqual(() => { }, () => { });
assert.notEqual([], []);
上面的代碼是對(duì)引用類型進(jìn)行的斷言測(cè)試,【notEqual() 】對(duì)于兩個(gè)對(duì)象的測(cè)試通過是一個(gè)【恒成立】的結(jié)果。
5.2 assert.notDeepEqual(actual, expected[, message])
【notDeepEqual() 】為 【deepEqual() 】的逆運(yùn)算,如果 actual!= expected 則斷言通過,不同于notEqual()的是對(duì)于引用類型是對(duì)值進(jìn)行判斷,不比對(duì)原型、不可枚舉屬性,只比對(duì)自有可枚舉屬性,斷言通過。
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');
// 斷言通過
上面代碼中最后一個(gè)表達(dá)式斷言通過,說明【不比對(duì)原型、不可枚舉屬性,只比對(duì)自有可枚舉屬性】
【注意??!】與notEqual的區(qū)別,也就是deepEqual和equal的區(qū)別,在引用數(shù)據(jù)類型的時(shí)候,deepEqual是比較的值而非引用,equal對(duì)比的是引用,所以引用類型在equal的時(shí)候是永遠(yuǎn)無法通過斷言測(cè)試的,以此類推,引用類型在notEqual時(shí)是永遠(yuǎn)否可以通過斷言測(cè)試的。
六. 判斷預(yù)期值和實(shí)際值嚴(yán)格不相等(!==)
上面總結(jié)到了判斷預(yù)期值和實(shí)際值嚴(yán)格相等,這兒總結(jié)一下判斷預(yù)期值和實(shí)際值嚴(yán)格不相等的兩個(gè)測(cè)試函數(shù),實(shí)際上就是上面 (四) 的逆運(yùn)算
6.1 assert.notStrictEqual(actual, expected[, message])
如果actual與expected不 !== 則斷言通過, 與 assert.deepStrictEqual() 相反
assert.notStrictEqual("1", 1);
// 斷言通過
assert.notStrictEqual("1", "1");
// AssertionError [ERR_ASSERTION]: '1' !== '1'
上面代碼是對(duì)值類型進(jìn)行的斷言測(cè)試,可以看出【notStrictEqual() 】考慮了數(shù)據(jù)類型
assert.notStrictEqual({ a: "foo" }, { a: "foo" });
assert.notStrictEqual(() => { }, () => { });
assert.notStrictEqual([], []);
上面代碼是對(duì)引用類型的測(cè)試,全部通過,以上表達(dá)式是恒通過的。
6.2 assert.notDeepStrictEqual(actual, expected[, message])
notDeepStrictEqual()就是deepStrictEqual()的逆運(yùn)算,如果 actual !== expected 則斷言通過,否則拋出AssertionError。
assert.notDeepStrictEqual({ a: '1' }, { a: 1 });
//斷言通過
assert.notDeepStrictEqual({ a: '1' }, { a: "1" });
//AssertionError [ERR_ASSERTION]: { a: '1' } notDeepStrictEqual { a: '1' }
七. 斷言錯(cuò)誤并拋出
這一組有 四 個(gè)(可以說是 三 個(gè))測(cè)試函數(shù),是對(duì)錯(cuò)誤進(jìn)行的處理。
7.1 assert.fail(message)
這個(gè)測(cè)試函數(shù)不多說,可以看錯(cuò)是下一個(gè)函數(shù)的重載,用于主動(dòng)拋出帶有【message】屬性的【AssertionError】對(duì)象
assert.fail("自定義錯(cuò)誤信息");
// AssertionError [ERR_ASSERTION]: 自定義錯(cuò)誤信息
7.2 assert.fail(actual, expected[, message[, operator[, stackStartFunction]]])
該測(cè)試函數(shù)用于主動(dòng)拋出自定義錯(cuò)誤信息,拋出錯(cuò)誤信息格式:【actual 參數(shù) + operator 參數(shù) + expected 參數(shù)】
assert.fail("BLUE","PINK");
// AssertionError [ERR_ASSERTION]: 'BLUE' != 'PINK'
上面代碼不提供【message】和【operator】,則【operator】默認(rèn)為 【!=】
assert.fail("BLUE","PINK","自定義的錯(cuò)誤信息");
// AssertionError [ERR_ASSERTION]: 自定義的錯(cuò)誤信息
assert.fail("BLUE","PINK","自定義的錯(cuò)誤信息","?",()=>{
console.log("hello");
});
// AssertionError [ERR_ASSERTION]: 自定義的錯(cuò)誤信息
上面代碼提供【message】,這時(shí)候 【actual】、【operator】、【expected】等參數(shù)會(huì)被列入錯(cuò)誤對(duì)象屬性中
assert.fail("BLUE","PINK",undefined);
// AssertionError [ERR_ASSERTION]: 'BLUE' undefined 'PINK'
assert.fail("BLUE","PINK",undefined,"?");
// AssertionError [ERR_ASSERTION]: 'BLUE' ? 'PINK'
上面代碼是【message】為 undefined 時(shí),會(huì)檢測(cè)【operator】參數(shù),【operator?operator:undefined 】
7.3 assert.throws(block,error, message)
參數(shù)說明:
block | Function
message | any
【說明??!】如果block拋出的錯(cuò)誤滿足error參數(shù),也就是拋出錯(cuò)誤與期望一致,則斷言通過,否則拋出block中的錯(cuò)誤,如果block不拋出錯(cuò)誤,則拋出【AssertionError 】。
【提示??!】error 參數(shù)可以是構(gòu)造函數(shù)、正則表達(dá)式、或自定義函數(shù)。
assert.throws(
() => {
throw new Error('錯(cuò)誤信息');
},
Error
);
上面代碼中 error 參數(shù)為構(gòu)造函數(shù),【block】拋出的錯(cuò)誤與預(yù)期的一致,所以斷言通過。
assert.throws(
() => {
throw new Error('錯(cuò)誤信息');
},
/錯(cuò)誤/
);
上面代碼中 error 參數(shù)為正則表達(dá)式,【block】拋出的錯(cuò)誤滿足正則表達(dá)式,所以斷言通過。
【注意?。 縠rror 參數(shù)不能是字符串。 如果第二個(gè)參數(shù)是字符串,則視為省略 error 參數(shù),傳入的字符串會(huì)被用于 【message】 參數(shù),
// 這是錯(cuò)誤的!不要這么做! assert.throws(myFunction, '錯(cuò)誤信息', '沒有拋出期望的信息'); // 應(yīng)該這么做。 assert.throws(myFunction, /錯(cuò)誤信息/, '沒有拋出期望的信息');
下面代碼,【error】 參數(shù)為自定義函數(shù)
assert.throws(
() => {
throw new Error('錯(cuò)誤信息');
},
function (err) {
if ((err instanceof Error) && /錯(cuò)誤/.test(err)) {
return true;
}
},
'不是期望的錯(cuò)誤'
);
7.4 assert.doesNotThrow(block, error, message)
【說明?。 款A(yù)期的錯(cuò)誤和實(shí)際的錯(cuò)誤一致時(shí),不拋出實(shí)際錯(cuò)誤,拋出AssertionError,不一致則拋出實(shí)際錯(cuò)誤信息
assert.doesNotThrow(
() => {
throw new TypeError('錯(cuò)誤信息');
},
SyntaxError
);
以上例子會(huì)拋出 TypeError,因?yàn)樵跀嘌灾袥]有匹配的錯(cuò)誤類型
assert.doesNotThrow(
() => {
throw new TypeError('錯(cuò)誤信息');
},
TypeError
);
以上例子會(huì)拋出一個(gè)帶有 Got unwanted exception (TypeError).. 信息的 AssertionError
assert.doesNotThrow(
() => {
throw new TypeError('錯(cuò)誤信息');
},
TypeError,
'拋出錯(cuò)誤'
);
// 拋出 AssertionError: Got unwanted exception (TypeError). 拋出錯(cuò)誤
上面代碼說明:如果拋出了 AssertionError 且有給 message 參數(shù)傳值,則 message 參數(shù)的值會(huì)被附加到 AssertionError 的信息中
八. 判斷值是否為真
這兒只有一個(gè)測(cè)試函數(shù)了
8.1 assert.ifError(value)
如果value的值為真或者可以轉(zhuǎn)換成true,則拋出value,否則斷言通過。
assert.ifError(true); //拋出true assert.ifError(false); //斷言通過
上面代碼中是直接給出的 布爾 類型的值,如果值為 true 則會(huì)將該值拋出,否則什么也不做
assert.ifError(0);
//斷言通過
assert.ifError("0");
//拋出 "0"
assert.ifError(1);
//拋出 1
assert.ifError(new Error());
//拋出 Error,對(duì)象名稱
上面代碼中全部是通過 Boolean(value) 轉(zhuǎn)換之后再進(jìn)行的測(cè)試,利用這個(gè)特性我們可以將此測(cè)試函數(shù)用于測(cè)試回調(diào)函數(shù)的 error 參數(shù)。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
使用puppeteer破解極驗(yàn)的滑動(dòng)驗(yàn)證碼
這篇文章主要介紹了利用puppeteer破解極驗(yàn)的滑動(dòng)驗(yàn)證功能,基本流程代碼實(shí)現(xiàn)給大家介紹的非常詳細(xì),需要的朋友可以參考下2018-02-02
Windows 系統(tǒng)下設(shè)置Nodejs NPM全局路徑
這篇文章主要介紹了Windows 系統(tǒng)下設(shè)置Nodejs NPM全局路徑2016-04-04
解決使用node命令提示:'node'不是內(nèi)部或外部命令,也不是可運(yùn)行的程序
最近在工作中遇到了個(gè)常見的問題,分享給大家,這篇文章主要給大家介紹了關(guān)于如何解決使用node命令提示:'node'不是內(nèi)部或外部命令,也不是可運(yùn)行的程序的相關(guān)資料,需要的朋友可以參考下2023-02-02

