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


期望 fn 函数抛出错误。

如果指定,则 error 可以是 ClassRegExp、验证函数,每个属性将被测试严格的深度相等的验证对象、或每个属性(包括不可枚举的 messagename 属性)将被测试严格的深度相等的错误实例。 使用对象时,还可以在对字符串属性进行验证时使用正则表达式。 请参阅下面的示例。

如果指定 message,则当 fn 调用无法抛出或错误验证失败时, message 将附加到 AssertionError 提供的消息。

自定义的验证对象/错误实例:

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'
    }
    // 注意,将仅测试验证对象上的属性。
    // 使用嵌套对象需要存在所有属性。
    // 否则验证将失败。
  }
);

// 使用正则表达式验证错误属性:
assert.throws(
  () => {
    throw err;
  },
  {
    // `name` 和 `message` 属性是字符串,使用正则表达式将匹配字符串。 
    // 如果失败,则会抛出错误。
    name: /^TypeError$/,
    message: /错误/,
    foo: 'bar',
    info: {
      nested: true,
      // 无法对嵌套属性使用正则表达式!
      baz: 'text'
    },
    // `reg` 属性包含一个正则表达式,
    // 并且只有当验证对象包含相同的正则表达式时,
    // 它才会通过。
    reg: /abc/i
  }
);

// 由于 `message` 和 `name` 属性不同而失败:
assert.throws(
  () => {
    const otherErr = new Error('未找到');
    otherErr.code = 404;
    throw otherErr;
  },
  err // 测试 `message`、 `name` 和 `code`。
);

使用构造函数验证 instanceof:

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

使用 RegExp 验证错误消息:

使用正则表达式在错误对象上运行 .toString,因此也将包含错误名称。

assert.throws(
  () => {
    throw new Error('错误值');
  },
  /^Error: 错误值$/
);

自定义的错误验证函数:

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

注意, error 不能是字符串。 如果提供了一个字符串作为第二个参数,则假定 error 被忽略,而字符串将用于 message。 这可能导致容易错过的错误。 使用与抛出的错误消息相同的消息将导致 ERR_AMBIGUOUS_ARGUMENT 错误。 如果使用字符串作为第二个参数,请仔细阅读下面的示例:

function throwingFirst() {
  throw new Error('错误一');
}
function throwingSecond() {
  throw new Error('错误二');
}
function notThrowing() {}

// 第二个参数是一个字符串,输入函数抛出一个错误。
// 第一种情况不会抛出,因为它与输入函数抛出的错误消息不匹配!
assert.throws(throwingFirst, '错误二');
// 在下一个示例中,传入的消息类似来自错误的消息,
// 并且由于不清楚用户是否打算实际匹配错误消息,
// 因此 Node.js 抛出了 `ERR_AMBIGUOUS_ARGUMENT` 错误。
assert.throws(throwingSecond, '错误二');
// 抛出错误:
// TypeError [ERR_AMBIGUOUS_ARGUMENT]

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

// 如果要匹配错误消息,请执行以下操作:
assert.throws(throwingSecond, /错误二$/);
// 因为错误消息匹配而不抛出。
assert.throws(throwingFirst, /错误二$/);
// 抛出错误:
// Error: 错误一
//     at throwingFirst (repl:2:9)

由于令人困惑的表示法,建议不要使用字符串作为第二个参数。 这可能会导致难以发现的错误。

Expects the function fn to throw an error.

If specified, error can be a Class, RegExp, a validation function, a validation object where each property will be tested for strict deep equality, or an instance of error where each property will be tested for strict deep equality including the non-enumerable message and name properties. When using an object, it is also possible to use a regular expression, when validating against a string property. See below for examples.

If specified, message will be appended to the message provided by the AssertionError if the fn call fails to throw or in case the error validation fails.

Custom validation object/error instance:

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'
    }
    // Note that only properties on the validation object will be tested for.
    // Using nested objects requires all properties to be present. Otherwise
    // the validation is going to fail.
  }
);

// Using regular expressions to validate error properties:
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 going
    // to pass.
    reg: /abc/i
  }
);

// Fails due to the different `message` and `name` properties:
assert.throws(
  () => {
    const otherErr = new Error('Not found');
    otherErr.code = 404;
    throw otherErr;
  },
  err // This tests for `message`, `name` and `code`.
);

Validate instanceof using constructor:

assert.throws(
  () => {
    throw new Error('Wrong value');
  },
  Error
);

Validate error message using RegExp:

Using a regular expression runs .toString on the error object, and will therefore also include the error name.

assert.throws(
  () => {
    throw new Error('Wrong value');
  },
  /^Error: Wrong value$/
);

Custom error validation:

assert.throws(
  () => {
    throw new Error('Wrong value');
  },
  function(err) {
    if ((err instanceof Error) && /value/.test(err)) {
      return true;
    }
  },
  'unexpected error'
);

Note that error cannot be a string. If a string is provided as the second argument, then error is assumed to be omitted and the string will be used for message instead. This can lead to easy-to-miss mistakes. Using the same message as the thrown error message is going to result in an ERR_AMBIGUOUS_ARGUMENT error. Please read the example below carefully if using a string as the second argument gets considered:

function throwingFirst() {
  throw new Error('First');
}
function throwingSecond() {
  throw new Error('Second');
}
function notThrowing() {}

// The second argument is a string and the input function threw an Error.
// The first case will not throw as it does not match for the error message
// thrown by the input function!
assert.throws(throwingFirst, 'Second');
// In the next example the message has no benefit over the message from the
// error and since it is not clear if the user intended to actually match
// against the error message, Node.js thrown an `ERR_AMBIGUOUS_ARGUMENT` error.
assert.throws(throwingSecond, 'Second');
// Throws an error:
// TypeError [ERR_AMBIGUOUS_ARGUMENT]

// The string is only used (as message) in case the function does not throw:
assert.throws(notThrowing, 'Second');
// AssertionError [ERR_ASSERTION]: Missing expected exception: Second

// If it was intended to match for the error message do this instead:
assert.throws(throwingSecond, /Second$/);
// Does not throw because the error messages match.
assert.throws(throwingFirst, /Second$/);
// Throws an error:
// Error: First
//     at throwingFirst (repl:2:9)

Due to the confusing notation, it is recommended not to use a string as the second argument. This might lead to difficult-to-spot errors.