Wednesday, 25th April 2012
Follow WikiJava on twitter now. @Wikijava

Expecting exceptions in junit 4.5

From WikiJava

Jump to: navigation, search


In this article I'll show you how you can use Junit 4.5 to unit test your code also when it comes to verify that certain exceptions are thrown.

This is something that can be easily worked around by executing your code embedding it in try/catch statements. but if you do so it's not as neat, and if you use a code coverage tool you'll be cheating it as it won't be able to if your code was run or not.

Contents

Explanation

When you are writing your unit test cases (which should be every time you write any code), you sometimes arrive to the situation where you want to test if your program throws the exceptions as expected or not.

The first impulse is always to embed the calls to your methods ini a try/catch, and to put a fail() command right after the method call. Something like follows:

	@Test
	public void testConstructorNull() {
		try {
			new DefaultDataSet(null, null, null);
			fail("null pointer exception was not thrown");
		} catch (NullPointerException e) {
			// success, exception was thrown.
		}
	}

This works fine, although it's not very elegant style. And it may be confusing to read some code that expects an Exception as the successful case.

Junit 4.5 offers us a way better way to do this using the Rules system, that is available in the framework.

  • The Rules are alterations of how the test methods are executed and reported.
  • The rules can be defined with the tag @Rule put before a public-non static field of the test class.

In the test class a rule is similar to an AOP function, that modifies how the test methods work, simplifying the writing of the testcases.

Each test method will have access to a separate version of the Rule, and can modify it. Additionally it's possible to write your own rules, which can be included in the junit 4 tests, the only requirement is to implement the MethodRule Interface. I won't go more into this here, as it's out of our scope.

This short introduction to Rules was necessary to fully understand the following example. where in my test class, I use one of the Rules predefined in Junit 4.5, the ExpectedException Rule.

This is how we are going to use the ExpectedException rule:

We will define a public field (non static) in the test class, as follows:

import org.junit.Rule;
import org.junit.rules.ExpectedException;
...
 
@Rule
public ExpectedException exception = ExpectedException.none();

This will add the rule for each of the test methods of the class. The ExpectedException.none(), although, means that we expect no exception from the methods.

Finally we'll have the test method where we want to test the Exception to be thrown to look like this:

	@Test
	public void testDefaultDataSet() {
		exception.expect(NullPointerException.class);
		new DefaultDataSet(null, null, null);
	}

This will modify the Rule just specifically for the test, and it makes so that the test will fail if (and only if) the test won't throw a NullPointerException.

Note, that the Test will not fail if the exception will be thrown before the exception.expect(NullPointerException.class); line. This is because at that point the line won't be executed, and the exception will prevent it from being executed at all.

Note also that the NullPointerException is a RunTimeException, therefore there's no need to throw it explicitly in the declaration of the method.

Note also the use of the @Before tag to indicate the method that is executed after the class is created and before the execution of each test Method. This is generally used to execute any code that would be otherwise repeated in all the test methods.

The full code

package org.wikijava.examples.junit;
 
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.wikijava.examples.junit.Product;
import org.wikijava.examples.junit.TestTools;
 
/**
 * @author Giulio Giraldi
 */
public class junitExample {
 
	private Product product;
 
	@Rule
	public ExpectedException exception = ExpectedException.none();
 
	@Before
	public void setUp() throws Exception {
		this.product = TestTools.createRandomProduct(100);
	}
 
	@Test
	public void testDefaultDataSet() {
		exception.expect(NullPointerException.class);
		//We expect an exception thrown from this constructor. 
		new DefaultDataSet(this.product, null, null);
	}
 
}


Alternative: 'expected' attribute

Alternatively, you can also use the expected attribute in @Test annotation:


public class junitExample {
 
	private Product product;
 
	@Before
	public void setUp() throws Exception {
		this.product = TestTools.createRandomProduct(100);
	}
 
        @Test(expected=NullPointerException.class) 
	public void testDefaultDataSet() {
		new DefaultDataSet(this.product, null, null);
	}
 
}


Comments from the users

To be notified via mail on the updates of this discussion you can login and click on watch at the top of the page


Comments on wikijava are disabled now, cause excessive spam.