assert-throws
is an assertion method for Node.js which checks if a synchronous or asynchronous function throws. It can also compare properties of the error (such as message
, code
and stack
and any other) with expected ones using string strict equality, a regular expression, or a function.
yarn add -D assert-throws
The package exports the default throws
function.
import throws from 'assert-throws'
async throws(
  config: {
    fn: function,
    args?: any|any[],
    context?: any,
    message?: Assertion,
    code?: Assertion,
    error?: Assertion,
    [prop]?: Assertion,
  },
): Error
Checks if a function throws an error. As a minimum, the function should be passed in the fn
property. If the assertion passes, the method returns the error which was thrown by the tested function.
!(string|RegExp|!Function)
_assertThrows.Assertion
: An assertion to perform.
_assertThrows.Config
: Parameters to the assert-throws
method.
Name | Type | Description |
---|---|---|
fn* | !Function | The function to test, either sync or async. |
args | (* | !Array<*>) | The arguments or single argument to pass to the function. |
context | * | The context in which to execute the function. Global context will be set by default. |
message | _assertThrows.Assertion | A string, regex, or function to test the message. |
code | _assertThrows.Assertion | A string, regex, or function to test the code. |
stack | _assertThrows.Assertion | A string, regex, or function to test the stack. |
prop | _assertThrows.Assertion | A string, regex, or function to test any other property of the error. |
error | Error | An error to perform strict comparison against. |
import throws from 'assert-throws'
async function testThrows() {
await new Promise(r => setTimeout(r, 100))
throw new Error('test-error')
}
(async function example() {
// 1. TEST a throwing function.
await throws({
fn: testThrows,
})
// 2. TEST a throwing function (alternative syntax).
await throws({
async fn(){
await testThrows()
},
})
console.log('Everything passed.')
})()
Everything passed.
import throws from 'assert-throws'
const testThrows = async () => {
await new Promise(r => setTimeout(r, 100))
}
(async function example() {
try {
await throws({
fn: testThrows,
})
} catch ({ stack }) {
console.log(stack)
}
})()
Error: Function testThrows should have thrown.
at example (/Users/zavr/adc/assert-throws/example/throws-fail.js:9:11)
at Object.<anonymous> (/Users/zavr/adc/assert-throws/example/throws-fail.js:15:3)
at Module.r._compile (/Users/zavr/adc/assert-throws/node_modules/alamode/depack/depack-lib.js:836:20)
at Object.l.(anonymous function).E._extensions.(anonymous function) [as .js] (/Users/zavr/adc/assert-throws/node_modules/alamode/depack/depack-lib.js:839:7)
To pass arguments to the tested function, the args
properties can be used.
import throws from 'assert-throws'
const testThrows = async (message, shouldThrow = true) => {
if (shouldThrow) throw new Error(message)
}
(async function example() {
try {
// 1. TEST that a function with arguments throws (pass).
await throws({
fn: testThrows,
args: ['An argument in the array'],
})
// 2. TEST that a function with an argument throws (pass).
await throws({
fn: testThrows,
args: 'A single argument',
})
// 2. TEST that a function with arguments throws (alternative) (pass).
await throws({
async fn() {
await testThrows('A single argument')
},
})
// 3. TEST that a function with arguments throws (fail).
await throws({
fn: testThrows,
args: ['An error occurred.', false],
})
} catch ({ stack }) {
console.log(stack)
}
})()
Error: Function testThrows should have thrown.
at example (/Users/zavr/adc/assert-throws/example/args.js:29:11)
at <anonymous>
To pass a context to the function, the context
properties can be set. Otherwise, it will use the global context, unless it was bound.
import throws from 'assert-throws'
async function testThrows() {
if (this.shouldThrow) throw new Error('An error occurred.')
}
(async function example() {
try {
// 1. TEST a function with context (pass).
await throws({
fn: testThrows,
context: { shouldThrow: true },
})
// 2. TEST a function with a context (fail).
await throws({
fn: testThrows,
})
} catch ({ stack }) {
console.log(stack)
}
})()
Error: Function testThrows should have thrown.
at example (/Users/zavr/adc/assert-throws/example/context.js:16:11)
at <anonymous>
If a function throws, any of the error properties can be tested. Every property specified in the configuration will test a property of the error, e.g., message
, code
and others.
It is possible to check that any property of a thrown error is equal to a given string.
import throws from 'assert-throws'
async function testThrows() {
await new Promise(r => setTimeout(r, 100))
throw new Error('test-error')
}
(async function example() {
try {
// 1. TEST that a function throws with a string (pass).
await throws({
fn: testThrows,
message: 'test-error',
})
// 2. TEST that a function throws with a string (fail).
await throws({
fn: testThrows,
message: 'wrong-error',
})
} catch ({ stack }) {
console.log(stack)
}
})()
Error: testwrong-error
test-error != wrong-error
at example (/Users/zavr/adc/assert-throws/example/string.js:17:11)
at <anonymous>
Moreover, a regular expression can be used to validate an error's property.
import throws from 'assert-throws'
async function testThrows() {
await new Promise(r => setTimeout(r, 100))
const error = new Error('test-error')
error.code = 'ENOENT'
throw error
}
(async function example() {
try {
// 1. TEST that a function throws with a regexp (pass).
await throws({
fn: testThrows,
code: /enoent/i,
})
// 2. TEST that a function throws with a regexp (fail).
await throws({
fn: testThrows,
code: /ENOEXMPL/,
})
} catch ({ stack }) {
console.log(stack)
}
})()
Error: ENOENT does not match regular expression /ENOEXMPL/
at example (/Users/zavr/adc/assert-throws/example/regexp.js:19:11)
at <anonymous>
For more advanced usage, a function can be used to test a property. It will receive the property of the error and should throw when an assertion does not pass.
import throws from 'assert-throws'
async function testThrows() {
await new Promise(r => setTimeout(r, 100))
const error = new Error('test-error')
throw error
}
(async function example() {
try {
// 1. TEST that a function throws with a function (pass).
await throws({
fn: testThrows,
stack(stack) {
if (!/at testThrows/.test(stack)) {
throw new Error('The function does not have the correct stack.')
}
},
})
// 2. TEST that a function throws with a function (fail).
await throws({
fn: testThrows,
stack(stack) {
if (/anonymous/.test(stack)) {
throw new Error('The function has an anonymous call stack line.')
}
},
})
} catch ({ stack }) {
console.log(stack)
}
})()
Error: The function has an anonymous call stack line.
at example (/Users/zavr/adc/assert-throws/example/function.js:22:11)
at <anonymous>
Any number of assertions can be added at the same time, and they will all be executed. However, only the first failing assertion will be presented.
import cleanStack from '@artdeco/clean-stack'
import throws from 'assert-throws'
async function testThrows() {
const err = new Error('test-error')
err.code = 'ENOTEST'
err.actual = -1
err.expected = Infinity
await new Promise(r => setTimeout(r, 100))
err.stack = cleanStack(err.stack)
throw err
}
(async function example() {
try {
// 1. TEST that a function throws with a regexp (pass).
await throws({
fn: testThrows,
message: 'test-error',
code: /TEST/,
stack(stack) {
if (/Module._compile/.test(stack)) {
throw new Error('The stack has a Node.js internal line.')
}
},
actual: -1,
expected: Infinity,
})
// 2. TEST that a function throws with a regexp (fail).
await throws({
fn: testThrows,
message: 'test-error',
code: /enotest/i,
stack(stack) {
if (/Module._compile/.test(stack)) {
throw new Error('The stack has a Node.js internal line.')
}
},
actual: -1,
expected: -Infinity,
})
} catch ({ stack }) {
console.log(stack)
}
})()
Error: -Infinity
Infinity != -Infinity
at example (/Users/zavr/adc/assert-throws/example/multiple.js:31:11)
at <anonymous>
assert-throws
allows to assert on a strict equality of an error.
import throws from 'assert-throws'
const error = new Error('test-error')
async function testThrows() {
await new Promise(r => setTimeout(r, 100))
throw error
}
(async function example() {
try {
// 1. TEST that a function throws the correct error (pass).
await throws({
fn: testThrows,
error,
})
// 1. TEST that a function throws the correct error (fail).
await throws({
fn: testThrows,
error: new Error('Another error.'),
})
} catch ({ stack }) {
console.log(stack)
}
})()
Error: Error: test-error is not strict equal to Error: Another error..
at example (/Users/zavr/adc/assert-throws/example/strict.js:19:11)
at <anonymous>
(c) Context Testing 2019