Friday, March 03, 2006

JUnit testing for exceptions

A JUnit pattern I find myself using very frequently is testing constructor and method inputs. Usually the first testcase I have for a new class is to test what happens in the constructor with null inputs. I believe in fail-fast coding principals and expect calls to quit as soon as they know there is no point in continuing. This helps me find bugs and other problems quickly during development rather than slowly during deployment.

So my typical test looks like this. For some class Foo whose constructor takes a single non-null parameter, bar, and which throws an IllegalArgumentException otherwise, I check for the name of the missing parameter in the exception message (as a convention):

 1 /**
 2  * Test {@link Foo#Foo(String)} for {@code null} <var>bar</var>.
 3  *
 4  * @throws Exception if unexpected
 5  */
 6 public void testFooForNullBar()
 7         throws Exception {
 8     try {
 9         new Foo(null);
10         fail("Did not throw");
11 
12     } catch (final IllegalArgumentException e) {
13         assertExceptionMessageContains(e, "bar");
14     }
15 }

But what about assertExceptionMessageContains? It is very simple:

 1 /**
 2  * Assert that the given exception, <var>e</var>, constains the given
 3  * string, <var>s</var>, in its message failing with <var>message</var>
 4  * otherwise.
 5  *
 6  * @param message the failure message
 7  * @param e the exception
 8  * @param s the string in the message
 9  */
10 protected static void assertExceptionMessageContains(final String message,
11         final Exception e, final String s) {
12     assertTrue(message, e.getMessage().contains(s));
13 }
14 
15 /**
16  * Assert that the given exception, <var>e</var>, constains the given
17  * string, <var>s</var>, in its message.
18  *
19  * @param e the exception
20  * @param s the string in the message
21  */
22 protected static void assertExceptionMessageContains(final Exception e,
23         final String s) {
24     assertExceptionMessageContains(
25             "Exception missing message: " + s + ": " + e, e, s);
26 }

Originally I threw NullPointerException from my constructors when encountering missing parameters, but over time I changed to IllegalArgumentException as more descriptive, and also so that any NullPointerException would always indicate something unexpected from the JVM.

No comments: