Unit Testing Exceptions with JUnit 4.5 Annotations

by

I not only decided to clean up all the unchecked warnings from the compiler, I decided to upgrade our unit testing framework to JUnit 4.5. There’s a very nice introduction to JUnit 4.5 at:

I just wrote a script with a bunch of regexes to transform our current tests into the new form. That meant taking every public void method whose name started with “test” and adding the annotation @Test. That is, my test methods now all meet this year’s look and feel for JUnit:

import org.junit.Test;
import static framework.junit.Asserts.assertEquals;

@Test
public void testSimple() {
    assertEquals(2,1+1);
}

I’m still not a big fan of the static import, which adds the method to the local namespace, but that’s the recommended practice, and I believe in following recommended practice more than I believe in innovating, at least for syntactic details like this.

Now if you want to test that a class throws an exception, what I used to do was this:

public void testException() {
    try {
        new HashSet().iterator().next(); 
        fail();
    } catch (java.util.NoSuchElementException e) {
        succeed();
    }
}

The pattern’s simple: set up a try/catch block, with the thing you expect to throw an exception in the try block. If the statement succeeds without an exception, you hit the fail method, which registers a test failure with JUnit. If you throw the exception, it gets caught and registers a test success. I had to implement the success method myself to register successes.

The recommended style for this test now is:

@Test(expected=java.util.NoSuchElementException.class)
public void testException() {
        new java.util.HashSet().iterator().next(); 
}

This certainly looks much cleaner. The test succeeds if and only if the exception is thrown.

Now consider this test, which has the same form as the testGamma() method in unit.io.BitInputTest:

 public void testElts() {
   java.util.Set<String> xs = new java.util.HashSet<String>();
   xs.add("foo");
   java.util.Iterator<String> it = xs.iterator();
   assertEquals("foo",it.next());
   try {
     it.next();
     fail();
    } catch (java.util.NoSuchElementException e) {
     succeed();
    }
   assertFalse(it.hasNext());
}

The test checks that the first call to next succeeds, the second throws an exception, then the has-next method returns false.

I can’t see how to do this in the new style. The first problem is that I don’t want the test to succeed if the first call to next throws an exception. So I’d have to write a separate test to make sure at least that part succeeds. But the real problem is the post test for has-next to return false, which I can’t figure out how to finagle into a test with an expected exception.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s