Unit testing functions in JavaScript using Jest sometimes requires checking if an exception was thrown, or testing the specific type of exception thrown.
Suppose we want to test the following function using Node.js and assert that it indeed throws an error:
func.js:
const func = () => { throw new Error('my error') } module.exports = func
func.test.js:
const func = require('./func') describe('exception test', () => { it('should throw an error', () => { expect(func).toThrow() }) })
Note that func should not be called within the expect; calling the function will cause the error to be thrown unexpectedly.
We can also assert that an error is not thrown using:
expect(func).not.toThrow()
If we need to assert the specific name of the thrown error, we can use the following form:
it('should throw an error', () => { expect(func).toThrowError('my error') })
If no exceptions are thrown, Jest will report:
Expected the function to throw an error. But it didn't throw anything.
Expecting Async Functions to Throw Exceptions
Writing a unit test to expect an async function to throw an exception can be done as follows. First we define the async function in a module, then in the test code we use the rejects property to test for any thrown errors. Essentially, we are asserting that our function causes a promise rejection.
async-func.js:
const func = async () => { throw new Error('my error') } module.exports = func
async-func.test.js:
const func = require('./async-func.js') describe('exception test', () => { it('should throw an error', async () => { await expect(func()).rejects.toThrow() }) })
Note that the function passed to it() is async itself so that we can use await inside.
Note also that func is called inside expect in this case; this will cause a promise rejection which can then be tested within the rejects property.
The case of testing for a specific error to be thrown inside the async function is similar and looks like this:
it('should throw an error', async () => { await expect(func()).rejects.toThrowError('my error') })
Expect a Function with Parameters to Throw an Exception
If we want to expect a function to throw an exception for certain input parameters, the key point is that we must pass in a function definition and not call our function inside the expect. The code is below for an example of a function which should throw an exception for negative integer inputs:
func.js:
const func = (n) => { if (n < 0) { throw new Error("negative input") } return n } module.exports = func
func.spec.js:
const func = require('./func.js') describe('exception test', () => { it('should throw an exception', () => { expect( () => func(-1) // Do not simply call func ).toThrow() }) })
We pass an anonymous function to expect, which will throw for the input. Expect can then determine that this function will throw.