How to Unit Test Custom Exceptions with QUnit
When writing robust JavaScript code, you will probably want to throw exceptions to let programmers know when they’ve misused your API. Sure, you could throw an instance of the built-in Error object, but then during unit testing how will you tell if the exception you’re seeing is yours and not coming from somewhere else?
The solution is to use a custom exception in your method, but this opens up a whole new can of worms. JavaScript’s weak typing and poor support for sub-classing Error mean that a custom exception class can easily be created with no error message, or even worse with no stack trace!
Today, I’m going to help you solve both these problems, and introduce you to a neat feature in QUnit that will help you unit test your methods.
Ok, let’s say you’ve written the following method for your class MyClass:
/**
* Does something interesting
*
* @param input {String} instructions
*/
method: function(input) {
if ((typeof input) === "string") {
// method implementation
}
throw new namespace.InvalidInputError("Input must be a string");
}
In the above method, we throw a custom InvalidInputError exception so that during unit testing we’ll be able to tell that the method failed specifically because the input was not a string. But how do we implement this custom exception so that it has all the properties we need? Here’s a good trick:
/**
* Raise this error whenever a method receives invalid input
*/
namespace.InvalidInputError = function(message) {
var error = new Error(message);
error.name = 'namespace.InvalidInputError';
throw error;
};
Here we’re doing something that seems strange: we’re throwing an exception any time you try to instantiate the exception class! But it turns out that implementing the Error sub-class this way lets us throw the exception in the typical manner, and creates an exception with everything we need: it has a unique name so we can differentiate it from other exceptions, it has a valid error message, and it has a valid stack trace. The only thing we can’t do with this trick is instantiate the sub-class and manipulate it afterward—but this is not a feature that we will ever need.
The last step is to create a unit test. We’re going to use QUnit. Here’s how to test our method:
test("method: non-string input throws InvalidInputError", function() {
throws(
function() {
this.myClass.method(5);
},
function(error) {
return error.name === "namespace.InvalidInputError";
}
);
});
In the above code, QUnit will execute the method with the invalid input of 5 in a try/catch block. It will then catch the generated exception and test its name attribute. If the exception is the right type then the test passes. Otherwise, if the test caused something else to throw an exception, or if no exception was thrown at all, then the test fails (QUnit Throws Documentation).
That’s it! You now know how to unit test exception handling in JavaScript. Please see the included JavaScript demo file for a working example. I hope that you found this helpful and look forward to hearing your feedback.
–Jonathan
This blog post is part of a series, like the following blog post to stay tuned and get updates about more topics around software engineering with SAPUI5 and JavaScript:
http://scn.sap.com/community/developer-center/front-end/blog/2013/12/12/engineering-in-javascript
Thanks, Jonathan! I found your blog post on google while searching for this topic and it helped me to find my solution.
Bests, Dusan
Thanks for your blog post.
I tried following your recipee, but I can't seem to make it work 🙁
If you have time to help out, could you take a look at the Stack Overflow question I made for my issue?
https://stackoverflow.com/questions/47602523/qunit-exception-testing