node.js學(xué)習(xí)之?dāng)嘌詀ssert的使用示例
一. 簡(jiǎn)介
斷言是編程術(shù)語(yǔ),表示為一些布爾表達(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í)通過(guò)斷言測(cè)試,否則拋出 【AssertionError】
const assert = require("assert"); assert("blue","第一個(gè)值為false時(shí)以我為錯(cuò)誤信息拋出"); assert(true,"第一個(gè)值為false時(shí)以我為錯(cuò)誤信息拋出");
上面一段代碼由于【Boolean(value)】全部為 true,所以全部通過(guò)斷言測(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()
的語(yǔ)法糖
const assert = require("assert"); assert.ok(true); assert.ok(1);
上面代碼【Boolean(value)】全部為 true,所以全部斷言通過(guò),下面是斷言不通過(guò)的情況,分別列出了默認(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í)際值是否相等,如果相等則斷言通過(guò),否則拋出 【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)行的比較,說(shuō)明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è)引用類型的值是沒法通過(guò)equal()
斷言的】
const obj={}; assert.equal(obj,obj); // 斷言通過(guò)
上面代碼由于比較的是同一個(gè)對(duì)象,兩個(gè)值得引用相等,所以斷言通過(guò)。
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'); // 斷言通過(guò) 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'); // 斷言通過(guò) assert.deepEqual(obj1, obj3, 'actual unequal to expected'); // AssertionError [ERR_ASSERTION]: actual unequal to expected
上面代碼是對(duì)引用類型的比較,可以看出【deepEqual()
】比較的是屬性值,而非引用,這是與equal()
不同的地方。
【注意??!】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"); // 斷言通過(guò)
上面代碼中 son1 和 son2 分別繼承與兩個(gè)不同的對(duì)象,都擁有 name 為 “Summer” 的屬性,最后的的結(jié)果是通過(guò),說(shuō)明【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】,說(shuō)明【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"); //斷言通過(guò) 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
,則斷言通過(guò),否則拋出AssertionError,message?message:
默認(rèn)錯(cuò)誤信息。
assert.strictEqual(1, 2); // 拋出 AssertionError: 1 === 2 assert.strictEqual(1, 1); // 測(cè)試通過(guò)。 assert.strictEqual(1, '1'); // 拋出 AssertionError: 1 === '1' assert.equal(1, '1'); // 測(cè)試通過(guò)。
【提示??!】對(duì)引用類型還是永遠(yuǎn)通不過(guò)【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
則斷言通過(guò),同樣對(duì)于值類型是單純對(duì)值進(jìn)行比較,對(duì)應(yīng)引用類型比較的是值得引用
assert.notEqual("1", "2"); // 斷言通過(guò) assert.notEqual("1", 2); // 斷言通過(guò) 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è)試通過(guò)是一個(gè)【恒成立】的結(jié)果。
5.2 assert.notDeepEqual(actual, expected[, message])
【notDeepEqual()
】為 【deepEqual()
】的逆運(yùn)算,如果 actual!= expected
則斷言通過(guò),不同于notEqual()
的是對(duì)于引用類型是對(duì)值進(jìn)行判斷,不比對(duì)原型、不可枚舉屬性,只比對(duì)自有可枚舉屬性,斷言通過(guò)。
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'); // 斷言通過(guò) assert.notDeepEqual(obj1,obj3,'actual equal to expected'); // 斷言通過(guò)
上面代碼中最后一個(gè)表達(dá)式斷言通過(guò),說(shuō)明【不比對(duì)原型、不可枚舉屬性,只比對(duì)自有可枚舉屬性】
【注意??!】與notEqual的區(qū)別,也就是deepEqual和equal的區(qū)別,在引用數(shù)據(jù)類型的時(shí)候,deepEqual是比較的值而非引用,equal對(duì)比的是引用,所以引用類型在equal的時(shí)候是永遠(yuǎn)無(wú)法通過(guò)斷言測(cè)試的,以此類推,引用類型在notEqual時(shí)是永遠(yuǎn)否可以通過(guò)斷言測(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不 !== 則斷言通過(guò), 與 assert.deepStrictEqual()
相反
assert.notStrictEqual("1", 1); // 斷言通過(guò) 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è)試,全部通過(guò),以上表達(dá)式是恒通過(guò)的。
6.2 assert.notDeepStrictEqual(actual, expected[, message])
notDeepStrictEqual()
就是deepStrictEqual()
的逆運(yùn)算,如果 actual !== expected
則斷言通過(guò),否則拋出AssertionError。
assert.notDeepStrictEqual({ a: '1' }, { a: 1 }); //斷言通過(guò) assert.notDeepStrictEqual({ a: '1' }, { a: "1" }); //AssertionError [ERR_ASSERTION]: { a: '1' } notDeepStrictEqual { a: '1' }
七. 斷言錯(cuò)誤并拋出
這一組有 四 個(gè)(可以說(shuō)是 三 個(gè))測(cè)試函數(shù),是對(duì)錯(cuò)誤進(jìn)行的處理。
7.1 assert.fail(message)
這個(gè)測(cè)試函數(shù)不多說(shuō),可以看錯(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ù)說(shuō)明:
block | Function
message | any
【說(shuō)明??!】如果block拋出的錯(cuò)誤滿足error參數(shù),也就是拋出錯(cuò)誤與期望一致,則斷言通過(guò),否則拋出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ù)期的一致,所以斷言通過(guò)。
assert.throws( () => { throw new Error('錯(cuò)誤信息'); }, /錯(cuò)誤/ );
上面代碼中 error 參數(shù)為正則表達(dá)式,【block】拋出的錯(cuò)誤滿足正則表達(dá)式,所以斷言通過(guò)。
【注意??!】error 參數(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)
【說(shuō)明??!】預(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ò)誤
上面代碼說(shuō)明:如果拋出了 AssertionError 且有給 message 參數(shù)傳值,則 message 參數(shù)的值會(huì)被附加到 AssertionError 的信息中
八. 判斷值是否為真
這兒只有一個(gè)測(cè)試函數(shù)了
8.1 assert.ifError(value)
如果value的值為真或者可以轉(zhuǎn)換成true,則拋出value,否則斷言通過(guò)。
assert.ifError(true); //拋出true assert.ifError(false); //斷言通過(guò)
上面代碼中是直接給出的 布爾 類型的值,如果值為 true 則會(huì)將該值拋出,否則什么也不做
assert.ifError(0); //斷言通過(guò) assert.ifError("0"); //拋出 "0" assert.ifError(1); //拋出 1 assert.ifError(new Error()); //拋出 Error,對(duì)象名稱
上面代碼中全部是通過(guò) 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-02Windows 系統(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