Testing for Exceptions with Jasmine

  • Estimated read time: 5 min read
  • Written by Chad Campbell on janv. 18 2014

Jasmine is a behavior-driven framework for testing code written in JavaScript. When you're writing code, exceptions may spring up expectedly or unexpectedly. If you're unit-testing your code, you may want to test for scenarios where exceptions are thrown. You could use the tried-and-true try-catch block approach. However, Jasmine provides the toThrow() and toThrowError() functions as an elegant alternative.

As you might expect, the toThrow() and toThrowError() functions check to see if some JavaScript throws an exception. The first function is used to see if a function throws an exception. The second lets you test deeper against a thrown exception. This blog post shows how to use these two functions. If you're interested, you can view the demo or download the code. For now, let's look at three testing scenarios.

Scenario #1: Testing a basic function that should throw an exception

Imagine for a second that you have a plain old JavaScript function that looks like the following:

function myProcedure() {
  throw 'The reason for the exception';
}

This function is fairly plain. It has a name. Yet, it does not take any parameters. Now, imagine you want to test this function. To test with Jasmine, you could do the following:

it('should throw an exception', function () {
  expect(myProcedure).toThrow();
});

This test uses Jasmine's behavior-driven development (BDD) style of testing. Take note of the fact that we referenced the name of the function that's being tested instead of calling it. In other words, myProcedure was used instead of myProcedure() (note the absence of parenthesis). If you include the parenthsis, the test results would show an error that says something like:

undefined: undefined

Not very descriptive. It is what it is though. Still, using the syntax above may raise another question. You might be wondering, how do I test a function that expects parameters?

Scenario #2: Testing a function that expects parameters

Pretend for a minute that you need to test a function that accepts parameters. The purpose of the function is to generate a random number and prefix it with a message. A function that does that may look like the following:

function myOtherProcedure(max, msg) {
  if ((!isNaN(parseFloat(max)) && isFinite(max)) === false) {
    throw new ArgumentException('You must provide a number');
  }

  if ((max === null) || (max < 1) || (max > 100)) {
    throw new ArgumentOutOfRangeException('The maximum value must be greater than 0 and less than 100.');
  }

  var result = Math.floor(Math.random() * max) + 1;
  return msg + result;
}

The function above takes two parameters: max and msg. With a function of this size, there are a few things to test. However, let's start by ensuring we can pass parameters to the function from a test. To create a test that passes parameters to a function, you need to do something like this:

it('should allow us pass in parameters', function () {
  expect(myOtherProcedure.bind(null, 10, 'you generated: ')).not.toThrow();
});

The test above tests the function that was previously defined and passes parameters to it. The parameters are passed with the help of the bind function. This function was introduced with ECMAScript 5. It basically creates a wrapper function so that you don't have to manually create an anonymous function. The context is maintained via the first parameter, which will usually be set to null or this. After you've passed that parameter in, you're free to add the parameters your function is expecting.

As more parameters are added, its more likely that there will be other things to test. With more things to test, there's a growing chance that you may return different types of exceptions to describe the problem. For that reason we'll look at a third scenario where different types of exceptions are involved.

Scenario #3: Testing a function that uses different types of exceptions

myOtherProcedure made use of two types of exceptions: ArgumentException and ArgumentOutOfRangeException. At first glance, you might assume these are part of the JavaScript language. While JavaScript is starting to add some built-in error types, if you download the code for this sample, you'll see those exception types are created like this:

function ArgumentException(message) {
  this.name = "ArgumentException";
  this.message = message || "Default Message";
}
ArgumentException.prototype = new Error();
ArgumentException.prototype.constructor = ArgumentException;

function ArgumentOutOfRangeException(message) {
  this.name = "ArgumentOutOfRangeException";
  this.message = message || "Default Message";
}
ArgumentOutOfRangeException.prototype = new Error();
ArgumentOutOfRangeException.prototype.constructor = ArgumentOutOfRangeException;

With Jasmine, we can still test code that makes use of custom exceptions. To help with that task, Jasmine has a new sibling to toThrow called toThrowError. A test using that function is shown here:

it('should require a valid maximum number for the first parameter', function () {
  expect(myOtherProcedure.bind(null, 101, 'you generated: ')).toThrowError(ArgumentOutOfRangeException);
  expect(myOtherProcedure.bind(null, 0, 'you generated: ')).toThrowError(ArgumentOutOfRangeException);
});

In the above example, the name of the exception type that's expected is passed to toThrowError. You have the option of passing either built-in exception types or custom exception types. The important piece is that the exception type extends JavaScript's Error object. This frees you up to test all kinds of exceptions with Jasmine.

This blog post showed you three ways to test for exceptions with Jasmine. You can view the demo or download the code. For the purposes of this blog post, Jasmine 2.0 was used. If you have any questions or comments related to this post, please leave them in the comments below. If you found this post helpful, I hope you will share this post via Google Plus, LinkedIn, or Twitter.


Comments

comments powered by Disqus

Chad Campbell
Chad Campbell

Chad is an independent software professional. He has been named a Microsoft MVP five times. His books have been translated into multiple languages and distributed worldwide. He holds a computer science degree from Purdue University, where he also studied psychology.

Chad has built sites, apps, frameworks, libraries, and platforms using Java, .NET, and Node. He's ran his own startups and has created software for Fortune 100 companies. In short, Chad knows how to create software. From ideation to delivery. From start-to-finish.


Follow Chad Online