Node.js之assert_2018.11.7

原创
2018/11/07 15:28
阅读数 335

20181018前记

  • 开始写nodeJs笔记,用于学习记录,通读一遍nodejs,记录知识点和不懂点,方便日后查看,所以内容基于官方文档,个别内容需要查找新资料,方便更好的理解,在查找资料的地方会注明出处~
  • 编辑器使用sublime, 安装了插件nodeJs,这样 “command+b”就可以运行代码,且在console里面显示出来~,刚开始乱码,修改package里面nodejs中的Nodejs.sublime-build中的编码格式. encoding": "utf8" 即可
  • 如果需要在sublime中实现node代码自动补全功能,需要安装SublimeCodeIntel,安装时间有点长,但是安装成功后,亲测有效~
  • <font color="red">当前的node版本api是基于v9.11.2</font>

hello-world.js

第一个例子,普遍helloworld,很显然是创建了一个server用来输出Hello world,服务器端会打印出 当前运行的主机名和端口号:217.0.0.1 3000

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World!\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

assert-断言

“The assert module provides a simple set of assertion tests that can be used to test invariants.”官方的定义,但是翻译过来为“assert模块提供了一组简单的断言测试,可用于测试不变量”。很显然,第一次反复琢磨这句话,没懂。仔细通读后发现,应该是用于<font color="red">断言</font>,即:预期值和实际值的一个对比,如果不同,则会抛出异常或者错误,用于单元测试应该比较多,可以提前发现和排除错误

虽然assert支持两种模式legacy和strict,但是官方建议使用strict模式,legacy模式已经被弃用

下面是assert相关的api方法:

1.strict模式

const assert = require('assert').strict;

assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]);

一开始执行的结果为<font color="blue">“TypeError: Cannot read property 'deepEqual' of undefined”</font>,查找了一下原因,发现我当时的node版本是8.几的,而我当前学习的node版本是9.几,所以,果然升级,升级过程如下:

sudo npm cache clean -f //清除nodejs的cache:
sudo npm install -g n //使用npm安装n模块
sudo n stable // 升级到稳定版本

成功安装到v10.12.0,再次执行上面assert的代码,就正常了~ 运行结果如下:

2.assert(value[, message]),assert.ok(value[, message])

assert()是assert.ok()的别名,所以直接研究assert.ok()就可以了

  • assert.ok(value[, message]):测试value是否为真值。如果value不为真,则抛出一个带有message属性(message 属性的值等于传入的 message 参数的值)的AssertionError,如果 message 参数为 undefined,则赋予默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError。 如果没有传入参数,则 message 会被设为字符串 'No value argument passed to assert.ok()'。
const assert = require('assert').strict;
assert.ok(true)     //正常运行
assert.ok(1)     //正常运行

assert.ok()     //AssertionError [ERR_ASSERTION]: No value argument passed to `assert.ok()`
assert.ok(false, '不是真值');   //AssertionError [ERR_ASSERTION]: 不是真值
assert.ok(typeof 123 === 'string');       
/* AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:   

assert.ok(typeof 123 === 'string') */
assert.ok(0);
// 抛出 AssertionError: The expression evaluated to a falsy value:
//
//   assert.ok(0)         
//   同assert.ok(false);
assert(0);
/* AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:

   assert(0) */

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

assert.deepEqual是 assert.deepStrictEqual()的别名,所以直接研究 assert.deepStrictEqual()就好

  • assert.deepStrictEqual(actual, expected[, message])用来测试 actual 参数与 expected 参数是否深度相等。
  • 如果两个值不相等,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则赋予默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError。
const assert = require('assert').strict;
assert.deepStrictEqual({ a: 1 }, { a: '1' });
/*
AssertionError [ERR_ASSERTION]: Input A expected to strictly deep-equal input B:
+ expected - actual

  {
-   a: 1
+   a: '1'
  }
 */

assert.deepStrictEqual(NaN, NaN);   //正常通过

assert.deepStrictEqual(0, -0);
/*
AssertionError [ERR_ASSERTION]: Input A expected to strictly deep-equal input B:
+ expected - actual

- 0
+ -0
 */

4.assert.doesNotReject(asyncFn[, error][, message]) <font color='red'>该方法实际上没有多大作用</font>

等待asyncFn的promise,如果asyncFn是一个函数,则立即调用该函数并等待返回的promise完成。然后它将检查承诺是否被拒绝。

  • 如果 asyncFn 是一个函数,并且同步抛出了一个错误, asser.doesNoReject()将抛出一个带有错误的被拒绝的promise。如果这个函数没有返回一个promise,assert.doesNotReject()将返回一个被拒绝的Promise,其中包含ERR_INVALID_RETURN_VALUE错误。在这两种情况下都会跳过错误处理程序。
  • 注意:assert.doesNotReject()实际上没有用,因为通过捕获拒绝然后再次拒绝它几乎没有什么好处。相反,请考虑在不应拒绝的特定代码路径旁边添加注释,并尽可能保持表达错误消息。
  • 如果指定,则错误可以是Class,RegExp或验证函数。有关更多详细信息,请参见<font color="red">assert.throws()。</font>

5.assert.doesNotThrow(fn[, error][, message]). <font color='red'>该方法实际上没有多大作用</font>

断言函数fn不会抛出错误。

  • 请注意:使用assert.doesNotThrow()实际上没有用,因为捕获错误然后重新抛出它没有任何好处。相反,请考虑在特定代码路径旁边添加注释,该注释不应抛出并尽可能保持错误消息。

6.assert.fail([message])

抛出 AssertionError,并带上提供的错误信息或默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError.

  • 其中fail带多个参数的方法已经被废弃
const assert = require('assert').strict;

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

assert.fail('失败');
// 抛出 AssertionError [ERR_ASSERTION]: 失败

assert.fail(new TypeError('失败')); 
/*
if (message instanceof Error) throw message;
TypeError: 失败
 */

7.assert.ifError(value)

如果value值不是undefined或者null,就抛出值,可用于测试回调函数的error参数。堆栈踪迹会包含传入ifError()的错误的所有帧,包括潜在的ifError()自身新增的帧。

const assert = require('assert').strict;

assert.ifError(undefined);
// 正常通过。 null也是正常通过
assert.ifError(0);
/*
throw newErr;
    ^
AssertionError [ERR_ASSERTION]: ifError got unwanted exception: 0
 */
assert.ifError('错误信息');
/*
throw newErr;
    ^
AssertionError [ERR_ASSERTION]: ifError got unwanted exception: '错误信息'
 */
assert.ifError(new Error());
/*
throw newErr;
    ^
AssertionError [ERR_ASSERTION]: ifError got unwanted exception: Error
 */

let err;
(function errorFrame() {
  err = new Error('错误信息');
})();

(function ifErrorFrame() {
  assert.ifError(err);
})();
/*
throw newErr;
    ^
AssertionError [ERR_ASSERTION]: ifError got unwanted exception: 错误信息
 */

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

测试actual和expected是否深度严格的不平等。与assert.deepStrictEqual()相反。

  • 如果两个值深度相等,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则会分配默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError。
const assert = require('assert').strict;

assert.notDeepStrictEqual({ a: 1 }, { a: '1' });
//正常通过

assert.notDeepStrictEqual({ a: 1 }, { a: 1});
/*
throw new AssertionError(obj);
  ^
AssertionError [ERR_ASSERTION]: Identical input passed to notDeepStrictEqual:

{
  a: 1
}
 */

assert.notDeepStrictEqual({ a: 1 }, { a: 1}, "深度相等");
/*
  throw new AssertionError(obj);
  ^
AssertionError [ERR_ASSERTION]: 深度相等
 */

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

其中assert.notEqual()是assert.notStrictEqual()的别名,所以直接研究assert.notStrictEqual()就好

  • 结合SameValue比较方法,判断actual和expected的值是否不全等
  • 如果两个值全等,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则赋予默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError。

10.assert.rejects(asyncFn[, error][, message])

等待asyncFn 的 promise,如果asyncFn是一个函数,则立即调用该函数并等待返回的promise完成。然后它将检查promise是否被拒绝。

  • 注意:除了等待的异步性质之外,完成行为与assert.throws()完全相同。

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

使用 SameValue比较法测试 actual 参数与 expected 参数是否全等。

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

12.assert.throws(fn[, error][, message])

期望函数fn抛出错误。

  • 如果特意指定的话,则错误可以是Class,RegExp,验证函数,验证对象,其中每个属性将被测试严格的深度相等,或者错误的实例,其中每个属性将被测试是斗严格的深度相等,包括不可枚举的消息和名称属性。
  • 使用对象时,在对字符串属性进行验证时,也可以使用正则表达式。
  • 如果fn调用无法抛出或错误验证失败,则消息将附加到AssertionError提供的消息。
  1. 自定义验证对象/错误实例:
const assert = require('assert').strict;
const err = new TypeError('Wrong value');
err.code = 404;
err.foo = 'bar';
err.info = {
  nested: true,
  baz: 'text'
};
err.reg = /abc/i;

<!-- 仅测试验证对象上的属性。 -->
<!-- 使用嵌套对象需要存在所有属性。否则验证将失败 -->
assert.throws(
  () => {
    throw err;
  },
  {
    name: 'TypeError',
    message: 'Wrong value',
    info: {
      nested: true,
      baz: 'text'
    }
  }
);
<!-- 测试通过 -->


assert.throws(
  () => {
    throw err;
  },
  {
    name: 'TypeError',
    message: 'Wrong value',
    info: {
      nested: true,
      baz: 'test'
    }
  }
);


<!-- AssertionError [ERR_ASSERTION]: Input A expected to strictly deep-equal input B:
+ expected - actual ... Lines skipped

Comparison {
    info: {
-     baz: 'text',
+     baz: 'test',
      nested: true
...
    name: 'TypeError'
  } a: 1
} -->



assert.throws(
  () => {
    throw err;
  },
  {
    name: 'TypeError',
    message: 'Wrong value',
    info: {
      nested: true,
      // baz: 'test'
    }
  }
);
<!-- 
 AssertionError [ERR_ASSERTION]: Input A expected to strictly deep-equal input B:
+ expected - actual ... Lines skipped
  Comparison {
    info: {
-     baz: 'text',
      nested: true
...
    name: 'TypeError'
  }
 -->

const assert = require('assert').strict;
const err = new TypeError('Wrong value');
err.code = 404;
err.foo = 'bar';
err.info = {
  nested: true,
  baz: 'text'
};
err.reg = /abc/i;

<!-- 使用正则表达式验证错误属性: -->
assert.throws(
  () => {
    throw err;
  },
  {
<!--     The `name` and `message` properties are strings and using regular
    expressions on those will match against the string. If they fail, an
    error is thrown. -->
    name: /^TypeError$/,
    message: /Wrong/,
    foo: 'bar',
    info: {
      nested: true,
      // It is not possible to use regular expressions for nested properties!
      baz: 'text'
    },
<!--     The `reg` property contains a regular expression and only if the
    validation object contains an identical regular expression, it is goingto pass. -->
    reg: /abc/i
  }
);
<!-- 通过 -->

//   由于`message`和`name`属性不同而失败:
assert.throws(
  () => {
    const otherErr = new Error('Not found');
    otherErr.code = 404;
    throw otherErr;
  },
  err // This tests for `message`, `name` and `code`.
);
<!-- 
AssertionError [ERR_ASSERTION]: Input A expected to strictly deep-equal input B:
+ expected - actual

  Comparison {
    code: 404,
-   message: 'Not found',
-   name: 'Error'
+   foo: 'bar',
+   info: {
+     baz: 'text',
+     nested: true
+   },
+   message: 'Wrong value',
+   name: 'TypeError',
+   reg: /abc/i
  }
 -->
  1. 自定义错误验证
assert.throws(
  () => {
    throw new Error('Wrong value');
  },
  function(err) {
    if ((err instanceof Error) && /value/.test(err)) {
      return true;
    }
  },
  'unexpected error'
);
  1. 请注意,错误不能是字符串。如果提供了一个字符串作为第二个参数,则假定错误被忽略,而字符串将用于消息。这可能导致easy-to-miss的错误。 使用与抛出的错误消息相同的消息将导致ERR_AMBIGUOUS_ARGUMENT错误。如果使用字符串作为第二个参数,请仔细阅读下面的示例:
const assert = require('assert').strict;
function throwingFirst() {
  throw new Error('First');
}
function throwingSecond() {
  throw new Error('Second');
}
function notThrowing() {}

//第二个参数是一个字符串,输入函数抛出一个错误。
//第一种情况不会抛出,因为它与错误消息不匹配,所以不会抛出异常,顺利执行
assert.throws(throwingFirst, 'Second');

// 在下一个示例中,消息对来自错误的消息没有任何好处,并且由于不清楚用户是否打算实际匹配错误消息,因此Node.js抛出了“ERR_AMBIGUOUS_ARGUMENT”错误。
assert.throws(throwingSecond, 'Second');
/*
hrow new ERR_AMBIGUOUS_ARGUMENT(
        ^
TypeError [ERR_AMBIGUOUS_ARGUMENT]: The "error/message" argument is ambiguous. The error message "Second" is identical to the message.
 */

// 该字符串仅在函数未抛出时使用(作为消息):
assert.throws(notThrowing, 'Second');
/*
throw new AssertionError(obj);
  ^
AssertionError [ERR_ASSERTION]: Missing expected exception: Second
 */

// 如果它打算匹配错误消息,请改为下面这样,并且不抛出因为错误消息匹配。
assert.throws(throwingSecond, /Second$/);       //顺利通过执行

assert.throws(throwingFirst, /Second$/);
/*
throw actual;
    ^
Error: First
 */
  • <font color="red"></font>由于令人困惑的表示法,建议不要使用字符串作为第二个参数。这可能会导致难以发现的错误
展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部