login
Blurts on the Art of Software Development

Today | RSS | RDF | Atom | Other Tags
Categories : All | All | CI | .NET | General | Humour | Java | Personal | Reviews | Ruby | SW Eng

Recently a lot of people have been asking how to test for expected exceptions. I kind of cover this in my book but since not everyone will buy it and considering that my old blog entry about creating suites with JUnit 4 is one of the most popular ones according to my logs, I thought I should write a quick blog post about it.

So here it is:

import static org.junit.Assert.fail;
import org.junit.Test;

public class TestExpectedExceptions {

    @Test
    public void testForExpectedExceptionWithTryCatch()
            throws Exception {
        try {
            Integer.parseInt("This should blow up...");

            // Uh-oh! No exception was thrown so we 
            // better make this test fail!
            fail("parseInt() should've thrown an exception!");
        } catch (NumberFormatException expected) {
            // this is exactly what we were expecting so 
            // let's just ignore it and let the test pass
        }
    }

    @Test(expected = NumberFormatException.class)
    public void testForExpectedExceptionWithAnnotation()
            throws Exception {
        Integer.parseInt("This should blow up...");
    }
}

In simple terms, here's what the above code snippet illustrates:

Classic Try-Catch Structure

The first test uses a JUnit 3 and 4 compatible try-catch structure for making sure that, if the code under test does not throw an exception, we'll fail the test case by invoking Assert#fail(). We leave the catch-block empty here but we could also make further asserts about what information we expect the thrown exception to contain. For example, we might assert that the exception's getMessage() method returns a description that contains some specific keyword.

Compact Annotation

The second test uses a JUnit 4-only feature that builds on the concept of annotations introduced into the language by the release of Java 5. In this less verbose example, we simply interact with the code under test in a way that we expect to cause an exception to be thrown. Normally, a test method throwing an exception would make JUnit flag that test as a failed one but since we have defined the expected parameter to our @Test annotation, JUnit instead fails if the method doesn't throw an exception (and, specifically, that type of an exception).

Which one should I use?

So these are the two options. If you're using JUnit 3, then your only option is the first one. If you're using JUnit 4, then you can choose between the two and decide, case by case, whether you like the compact form more. The compact form does not allow assertions against the thrown exception, though, beyond its type so you'll probably end up using both anyway.

I hope this was helpful.