Node.js API 之 assert 断言

步骤

  • 全局安装 mocha
npm install mocha -g
  • Fork 代码仓库并拉到本地
  • 启动测试
mocha
  • 打开 ./test/test.js 修改代码跑通测试用例

参考

API

assert 模块是Node的内置模块,主要用于断言。如果表达式不符合预期,就抛出一个错误。assert模块一共提供11个方法。

assert(value[, message])

参数

  • value <any> bool
  • message <any> string

assert.ok()的别名。

assert方法接受两个参数,当第一个参数对应的布尔值为true时,不会有任何提示,返回undefined。当第一个参数对应的布尔值为false时,会抛出一个错误,该错误的提示信息就是第二个参数设定的字符串。

栗子

var assert = require('assert');

function add (a, b) {
    return a + b;
}

var expect = add(1, 2);
assert(expect === 3, '预期1加2等于3');

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

参数

  • actual <any> 实际值
  • expected <any> 预期值
  • message <any> 错误提示信息

使用相等运算符(==)测试actual参数与expected参数是否相等。

举栗

// 再次使用上面的栗子

assert.equal(6, add(3, 3), '预期 3 + 3 等于 6')

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

参数

  • actual <any> 实际
  • expected <any> 预期
  • message <any> 错误提示信息

deepEqual方法用来测试 actual 参数与 expected 参数是否深度相等。 原始值使用相等运算符(==)比较。只要它们的属性一一对应,且值都相等,就认为两个对象相等,否则抛出一个错误。

举🌰

// 格式
assert.deepEqual(actual, expected[, message])

// 栗子

var assert = require('assert');

let list1 = [1, 2, 3, 4, 5];
let list2 = [1, 2, 3, 4, '5'];

assert.deepEqual(list1, list2, '预期两个数组应该有相同的属性');

let person1 = { "name":"john", "age":"21" };
let person2 = { "name":"john", "age":"21" };

assert.deepEqual(person1, person2, '预期两个对象应该有相同的属性');

deepEqual()只测试可枚举的自身属性,不测试对象的原型、连接符、或不可枚举的属性(这些情况使用 assert.deepStrictEqual()。 例如,下面的例子不会抛出 AssertionError,因为 RegExp 对象的属性不是可枚举的:

// 不会抛出 AssertionError。
assert.deepEqual(/a/gi, new Date());

MapSet 包含的子项也会被测试。

子对象中可枚举的自身属性也会被测试:

const assert = require('assert');

let obj1 = { a: { b: 1 } };
let obj2 = { a: { b: 1 } };

assert.deepEqual(obj1, obj1);

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

参数

  • actual <any> 实际
  • expected <any> 预期
  • message <any> 错误提示信息

严格要求上的深度比较,专属指定了某一类;与 assert.deepEqual() 大致相同,但有一些区别:

  1. 原始值使用全等运算符(===)比较。Set 的值与 Map 的键使用 SameValueZero 比较。
  2. 对象的原型也使用全等运算符比较。
  3. 对象的类型标签要求相同。
  4. 比较[对象包装器][]时,其对象和里面的值要求相同。

举🌰

// 继续上一个栗子
let list1 = [1, 2, 3, 4, 5];
let list2 = [1, 2, 3, 4, '5'];

assert.deepEqual(list1, list2, '预期两个数组应该有相同的属性');
// 测试通过,因为 5 == '5'; 原始值的比较还是 使用相等运算符

assert.deepStrictEqual(list1, list2, '预期两个数组应该有相同的属性且值相等,类型也要相等');

assert.doesNotThrow(block[, error][, message])

参数

  • block <Function> 执行函数
  • error <RegExp> | <Function> 指定错误类型参数
  • message <any> 错误提示信息

doesNotThrow方法与throws方法正好相反,预期某个代码块不抛出错误。

  • 断言 block 函数不会抛出错误。
  • 当 assert.doesNotThrow() 被调用时,它会立即调用 block 函数。
  • 如果抛出错误且错误类型与 error 参数指定的相同,则抛出 AssertionError。 如果错误类型不相同,或 error 参数为 undefined,则抛出错误。

举🌰

// 以下例子会抛出 TypeError,因为在断言中没有匹配的错误类型:

assert.doesNotThrow(
  () => {
    throw new TypeError('错误信息');
  },
  SyntaxError
);


// 如果抛出了 AssertionError 且有给 message 参数传值,则 message 参数的值会被附加到 AssertionError 的信息中:
assert.doesNotThrow(
  () => {
    throw new TypeError('错误信息');
  },
  TypeError,
  '抛出错误'
);
// 抛出 AssertionError: Got unwanted exception (TypeError). 抛出错误

assert.fail(message)

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

参数

  • actual <any> 实际值
  • expected <any> 预期值
  • message <any> 错误提示信息
  • operator <string> 默认为 '!='。 操作符
  • stackStartFunction <function> 默认为 assert.fail。 用于拦截异常栈信息

fail方法用于抛出一个错误。但是不管参数是什么值,它总是抛出一个错误.

抛出 AssertionError。 如果 message 参数为空,则错误信息为 actual 参数 + operator 参数 + expected 参数。 如果只提供了 actual 参数与 expected 参数,则 operator 参数默认为 '!='。 如果提供了 message 参数,则它会作为错误信息,其他参数会保存在错误对象的属性中。 如果提供了 stackStartFunction 参数,则该函数上的栈帧都会从栈信息中移除(详见 Error.captureStackTrace)。

举🌰

const assert = require('assert');

assert.fail(1, 2, undefined, '>');
// 抛出 AssertionError [ERR_ASSERTION]: 1 > 2

assert.fail(1, 2, '错误信息');
// 抛出 AssertionError [ERR_ASSERTION]: 错误信息

assert.fail(1, 2, '错误信息', '>');
// 抛出 AssertionError [ERR_ASSERTION]: 错误信息
// 上面两个例子的 `actual` 参数、`expected` 参数与 `operator` 参数不影响错误消息。

assert.fail();
// 抛出 AssertionError [ERR_ASSERTION]: Failed

assert.fail('错误信息');
// 抛出 AssertionError [ERR_ASSERTION]: 错误信息

assert.fail('a', 'b');
// 抛出 AssertionError [ERR_ASSERTION]: 'a' != 'b'

例子,使用 stackStartFunction 参数拦截异常的栈信息:

function suppressFrame() {
  assert.fail('a', 'b', undefined, '!==', suppressFrame);
}
suppressFrame();
// AssertionError [ERR_ASSERTION]: 'a' !== 'b'
//     at repl:1:1
//     at ContextifyScript.Script.runInThisContext (vm.js:44:33)
//     ...

assert.ifError(value)

参数

  • value <any>

如果 value 为真,则抛出 value。 可用于测试回调函数的 error 参数。
ifError方法断言某个表达式是否false,如果该表达式对应的布尔值等于true,就抛出一个错误。它对于验证回调函数的第一个参数十分有用,如果该参数为true,就表示有错误。

举🌰

// 格式
assert.ifError(value)

// 用法
function sayHello(name, callback) {
  var error = false;
  var str   = "Hello "+name;
  callback(error, str);
}

// use the function
sayHello('World', function(err, value){
  assert.ifError(err);
  // ...
})

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

参数

  • actual <any> 实际
  • expected <any> 预期
  • message <any> 错误提示信息

测试 actual 参数与 expected 参数是否不深度相等。 与 assert.deepEqual() 相反。

举🌰

// 格式
assert.notDeepEqual(actual, expected, [message])

// 例子
var assert = require('assert');

var list1 = [1, 2, ,3, 4, 5];
var list2 = [1, 2, 3, 4, 5];

assert.notDeepEqual(list1, list2, '预期两个对象不相等');

var person1 = { "name":"john", "age":"21" };
var person2 = { "name":"jane", "age":"19" };

// deepEqual checks the elements in the objects are identical
assert.notDeepEqual(person1, person2, '预期两个对象不相等');

let obj1 = { a: { b: 1 } };
let obj2 = { a: { b: 1 } };

assert.notDeepEqual(obj1, obj1);
// 抛出 AssertionError: { a: { b: 1 } } notDeepEqual { a: { b: 1 } }

如果两个值深度相等,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则赋予默认的错误信息。

assert.notDeepStrictEqual(actual, expected[, message])

参数

  • actual <any> 实际
  • expected <any> 预期
  • message <any> 错误提示信息

测试 actual 参数与 expected 参数是否不深度全等。 与 assert.deepStrictEqual() 相反。

举🌰

const assert = require('assert');

assert.notDeepEqual({ a: 1 }, { a: '1' });
// 抛出 AssertionError: { a: 1 } notDeepEqual { a: '1' }

assert.notDeepStrictEqual({ a: 1 }, { a: '1' });
// 测试通过。

如果两个值深度全等,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则赋予默认的错误信息。

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

参数

  • actual <any> 实际
  • expected <any> 预期
  • message <any> 错误提示信息

使用不等运算符(!=)测试 actual 参数与 expected 参数是否不相等。

举🌰

const assert = require('assert');

assert.notEqual(1, 2);
// 测试通过。

assert.notEqual(1, 1);
// 抛出 AssertionError: 1 != 1

assert.notEqual(1, '1');
// 抛出 AssertionError: 1 != '1'

如果两个值相等,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则赋予默认的错误信息。

assert.notStrictEqual(actual, expected[, message])

参数

  • actual <any> 实际
  • expected <any> 预期
  • message <any> 错误提示信息

使用不全等运算符(!==)测试 actual 参数与 expected 参数是否不全等。

举🌰

const assert = require('assert');

assert.notStrictEqual(1, 2);
// 测试通过。

assert.notStrictEqual(1, 1);
// 抛出 AssertionError: 1 !== 1

assert.notStrictEqual(1, '1');
// 测试通过。

如果两个值全等,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则赋予默认的错误信息。

assert.ok(value[, message])

  • value <any>
  • message <any> 错误提示信息

测试 value 是否为真值。 相当于 assert.equal(!!value, true, message)。

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

const assert = require('assert');

assert.ok(true);
// 测试通过。
assert.ok(1);
// 测试通过。
assert.ok(false);
// 抛出 "AssertionError: false == true"
assert.ok(0);
// 抛出 "AssertionError: 0 == true"
assert.ok(false, '不是真值');
// 抛出 "AssertionError: 不是真值"

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

参数

  • actual <any> 实际
  • expected <any> 预期
  • message <any> 错误提示信息

使用全等运算符(===)测试 actual 参数与 expected 参数是否全等。

举🌰

const assert = require('assert');

assert.strictEqual(1, 2);
// 抛出 AssertionError: 1 === 2

assert.strictEqual(1, 1);
// 测试通过。

assert.strictEqual(1, '1');
// 抛出 AssertionError: 1 === '1'

如果两个值不全等,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则赋予默认的错误信息。

assert.throws(block[, error][, message])

参数

  • block <Function> 执行函数
  • error <RegExp> | <Function> 指定错误类型参数
  • message <any> 错误提示信息

断言 block 函数会抛出错误。

error 参数可以是构造函数、正则表达式、或自定义函数。

如果指定了 message 参数,则当 block 函数不抛出错误时,message 参数会作为 AssertionError 的错误信息。

throws方法预期某个代码块会抛出一个错误,且抛出的错误符合指定的条件。

举🌰

例子,error 参数为构造函数:

assert.throws(
  () => {
    throw new Error('错误信息');
  },
  Error
);

例子,error 参数为正则表达式:

assert.throws(
  () => {
    throw new Error('错误信息');
  },
  /错误/
);

例子,error 参数为自定义函数:

assert.throws(
  () => {
    throw new Error('错误信息');
  },
  function(err) {
    if ((err instanceof Error) && /错误/.test(err)) {
      return true;
    }
  },
  '不是期望的错误'
);

error 参数不能是字符串。 如果第二个参数是字符串,则视为省略 error 参数,传入的字符串会被用于 message 参数。 例如:

// 这是错误的!不要这么做!
assert.throws(myFunction, '错误信息', '没有抛出期望的信息');

// 应该这么做。
assert.throws(myFunction, /错误信息/, '没有抛出期望的信息');

注意事项

对于 SameValueZero 比较,建议使用 ES2015 的 Object.is()。

const a = 0;
const b = -a;
assert.notStrictEqual(a, b);
// 抛出 AssertionError: 0 !== -0
// 因为全等运算符不区分 -0 与 +0。
assert(!Object.is(a, b));
// 但 Object.is() 可以区分。

const str1 = 'foo';
const str2 = 'foo';
assert.strictEqual(str1 / 1, str2 / 1);
// 抛出 AssertionError: NaN === NaN
// 因为全等运算符不能用于测试 NaN。
assert(Object.is(str1 / 1, str2 / 1));
// 但 Object.is() 可以测试。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容