HiveBrain v1.2.0
Get Started
← Back to all entries
debugjavaMinor

Simple helper method for JUnit3 tests

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
simplemethodhelpertestsforjunit3

Problem

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 exceptionClass, Runnable runnable) {
        try {
            runnable.run();
            throw new AssertionFailedError(
                         "Expected exception: ");
        } catch (Exception e) {
            if (!exceptionClass.equals(e.getClass())) {
                throw new AssertionFailedError(
                        "Expected exception:  " +
                        "but was: "
                );
            }
        }
    }
}


Using:

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

Solution

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:  " +
                    "but was: "
            );
            tothrow.initCause(e);
            throw tothrow;

Code Snippets

if (!exceptionClass.equals(e.getClass())) { ....
TestingUtils.assertExpectedException(SQLException.class, ....);
if (!exceptionClass.isInstance(e)) {....
AssertionFailedError tothrow = new AssertionFailedError(
                    "Expected exception: <" + exceptionClass.getName() + "> " +
                    "but was: <" + e.getClass().getName() + ">"
            );
            tothrow.initCause(e);
            throw tothrow;

Context

StackExchange Code Review Q#41141, answer score: 5

Revisions (0)

No revisions yet.