Overview
Test if a function throws or not, and optionally if it throws the right thing.
Created to ease testing of errors when using yaba, but can be used anywhere you'd like.
{ if typeof arg !== "number" throw "The argument is invalid. " + arg + " is not a number." } // The following assertions pass. // Note case insensitivity. // The following assertions do not pass (wrong error type, non-matching message). throwssplitChar = ";"throwssplitChar = "|"throwssplitChar = "," // Note that you can put `new` in front of `Error` and `TypeError` if you think that reads better.
What it can look like in CoffeeScript:
assert throws Error"string||string2"-> fn"invalid""args"
Installation
npm install throws
or component install lydell/throws
CommonJS: var throws = require("throws")
AMD and regular old browser globals: Use ./throws.js
Tests
Node.js: npm test
Browser: Open ./test/browser/index.html
Usage
throws(fn, ...args)
Runs fn(...args)
. Returns true
if it throws. Otherwise false
.
throws(test, fn, ...args)
Runs fn(...args)
. Returns false
if it does not throw. Otherwise the caught error
is compared
to test
.
First off, test
must be one of two things:
- An error instance (
test instanceof Error
). If so,error instanceof test.constructor
is checked. - An error constructor (a subclass of
Error
orError
itself). If so,error instanceof test
is checked.
Secondly, the message
properties (if any) of error
and test
are compared. test.message
is a
pipe ("|") separated string of substrings and regexes. error.message
must contain all substrings,
case insensitively, and match all regexes.
-
To keep things simple, a substring cannot contain a pipe ("|")—there are no escape rules. Instead there is the possibility to change it to something else, via
throws.splitChar
. -
It is, however, possible to escape a regex. They are recognized by a substring beginning with a slash ("/"). Double it to denote an actual substring starting with a slash:
"/a/"
is the regex/a/
, while"//a/"
is the substring"/a/"
. -
If the string starts and ends with a pipe, the whole
message
property of the error must exactly match the string.
If both these tests pass, true
is returned. Otherwise false
.
throws.messageHolder
When throws returns false
, it sets throws.messageHolder.message
to a string explaining why it
did so. This way, you could let other tools use that information.
For example, if you use yaba, you can set throws.messageHolder = yaba
. Then yaba will put the
reason the throws test failed in its assertion errors.
Background
I like testing with assert
, but testing error throwing without a helper function is cumbersome. I
wanted something that fit well with the use of a simple assert function, and let me check the type
of the error, and that certain important key words were present in the error message. After a while
I came up with the idea of comparing to another error instance. Initially I thought about passing an
array of substrings and regexes (new Error(["a", "b", /c/])
), but I then realized that the message
is always converted to a string. After finding out that .toString()
on regexes give a perfect
representation, I understood that it was still possible (and I enjoyed parsing the string!). Best of
all is that passing new Error(/my regex/i)
is totally possible—it looks really nice!
"But I want to check more things on my errors!"
Then throws
probably isn't for you (but don't hesitate to open new issues about it). Either find
something else, or use a good old try/catch:
var errortry catcherr error = err
try fninvalidargscatch errorassert error?lineNumber is 4