Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected exceptions in Java Unit tests

I'm really a newbie to JUnit and unit testing in general and I'm struggling to find the right approach. What is the better way to deal with unexpected exceptions, and why?

Method A:

  1. first catch the expected ones, fail the test with a message
  2. in the last catch block, catch a general Exception and fail the test with some "Unexpected exception has occured" message

Method B:

  1. catch only the expected ones, fail with a message
  2. mark the test method with throws Exception and let anything unexpected "bubble up" completely out of the test

And to add to the confusion, by saying "unexpected exception", I mean either one of these things:

  1. an exception that the method being tested claims to throw, but on in this case. For example, my method throws IllegalArgumentException and NullPointerException, but in this try block, I expect it to throw IllegalArgument; NullPointer is considered unexpected. Catch and fail or bubble up?
  2. a general Exception I really cannot anticipate

I'm aware this question comes out a bit confusing, I'm getting lost in it myself, but hopefully someone will give me any kind of hint. Won't blame you for downvotes, it's still worth the risk :)

like image 265
oli.G Avatar asked Aug 11 '26 12:08

oli.G


1 Answers

I got the feeling, none of the answers so far really got to the point of the question. The OP explicitly asks for the handling of unexpected exceptions. My two cents on this topic are:

It depends on the level of verbosity you want to achieve:

Usually, you should strive for short tests which pinpoint one aspect of the code. Ideally, only a handful of methods need to be called and only one or two of them may raise an unexpected exception. In this case, adding a throws-clause for all checked exceptions should be sufficient to analyze the problem when you test fails. I prefer this solution because it's easier to write, shorter and more comprehensive.

Example:

@Test
public void testPrivateMethod() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

    //...

    Method method = MyClass.class.getMethod("privateMethod");
    method.setAccessible(true);
    boolean result = method.invoke(myInstance);
    assertTrue(result);
}

If the test code needs to be more complicated multiple methods may be responsible for raising an exception. Probably, some of them even throw exceptions of the same kind. In this case, try-catch blocks may be beneficial for locating the problem when your test case fails. However, this produces more code and may render the tests less readable.

Example:

@Test
public void testPrivateMethod() {

    //...

    Method method;
    try {
        Method method = MyClass.class.getMethod("privateMethod");
        method.setAccessible(true);
        boolean result = method.invoke(myInstance);
        assertTrue(result);
    } catch (NoSuchMethodException | SecurityException e) {
        fail("Could not access method 'privateMethod'.");
    } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
        fail("Call to 'privateMethod' raised an exception.")
    }
}

I hope I got the intention of the question right.

like image 156
Johnson Avatar answered Aug 13 '26 02:08

Johnson