# Simple helper method for JUnit3 tests

In JUnit 3, I cannot tell JUnit what type of exception is expected. In JUnit 4, the declaration @Test(expected=NullPointerException.class) does it.

But, unfortunately in Android development, I can use only JUnit 3. So I wrote this simple method:

public class TestingUtils {

public static void assertExpectedException(
Class<? extends Exception> exceptionClass, Runnable runnable) {
try {
runnable.run();
throw new AssertionFailedError(
"Expected exception: <" + exceptionClass.getName() + ">");
} catch (Exception e) {
if (!exceptionClass.equals(e.getClass())) {
throw new AssertionFailedError(
"Expected exception: <" + exceptionClass.getName() + "> " +
"but was: <" + e.getClass().getName() + ">"
);
}
}
}
}


Using:

public void testConstructorThrowsExceptionIfArgumentIsNull() {
TestingUtils.assertExpectedException(IllegalArgumentException.class, new Runnable() {
@Override
public void run() {
new SomeTestedClass(null);
}
});
}

-
The message for the case if it is was not thrown should be clearer, including something like "Expected exception X, but was not thrown". – Bobby Feb 7 '14 at 10:12
@Bobby thank you :) – leonideveloper Feb 7 '14 at 10:25
FYI, I have done something similar in JDOM and I use it like this. – rolfl Feb 7 '14 at 11:23

I have been though this loop before. I chose to do things in a slightly different way to you, in that instead of creating a Runnable, I instead add a try/catch block to the actual test.

Each system has pros/cons, but the differences are really cosmetic. Using a Runnable does make the JUnit logic better contained in the utility code.... but makes calling the utility test code a little bit more complicated. I am not sure which one I prefer.

I have a suggestion regarding this line here:

if (!exceptionClass.equals(e.getClass())) { ....


It is useful to be able to expect a super-type of an exception. For example, you want to trap an SQLException when you run a query, or you want to trap an IOException when you do something on a Stream..... you have the code:

TestingUtils.assertExpectedException(SQLException.class, ....);


but, the actual exception may be com.ibm.db2.jdbc.xxx.PicnicException, which is a subclass of SQLException.

Using equals() to match the exceptions is a problem.... you should use:

if (!exceptionClass.isInstance(e)) {....


One other thing, which is android specific.....

I found a bug in the Android Dalvik implementation/SDK relating to this problem... you should be setting the 'cause' for your AssertionError so that it is logged correctly. Unfortunately, the bug (which is fixed in Jelly-Bean) makes this impossible.

If you are sure you will be testing on Jelly-Bean or newer (the bug was fixed a while ago), you should also be initializing the cause on your AssertionError:

            AssertionFailedError tothrow = new AssertionFailedError(
"Expected exception: <" + exceptionClass.getName() + "> " +
"but was: <" + e.getClass().getName() + ">"
);
tothrow.initCause(e);
throw tothrow;

-