Java Testing Tip #1:


Don’t Assert.fail() on Exception, Wrap With AssertionError Instead

Recently while updating and writing tests, I ran into a pattern:

try {
    /* Tested code here... */
}
catch (Exception e) {
    Assert.fail("Exception was thrown with message: " + e.getMessage());
}

Many times when developers are writing tests, they run into a similar situation where throwing an exception should result in a test failure. An uncuaght exception causes a test error, so the exception is caught and Assert.fail() is called to fail the test instead. The above code is certainly correct, but it also hides all the information that the original exception contained. Here is the output of an example test (run with the maven-surefire-plugin) which utilizes Assert.fail():

assertFailTest(com.sandbox.SandboxTest)  Time elapsed: 0.009 sec  <<< FAILURE!
java.lang.AssertionError: Exception was thrown with message: Exception 1
	at com.sandbox.SandboxTest.assertFailTest(SandboxTest.java:31)

As you can see, any information aside from the message of the original exception has been lost. Thankfully, Java offers an elegant solution: AssertionError. AssertionError has a two-arg constructor which takes a message and a Throwable. When an AssertionError is thrown, the test result will still be listed as a failure. In fact, all that Assert.fail() does under the hood is throw an AssertionError with a message. So, next time you need to fail a test when an exception is thrown, use throw new AssertionError("message", e); to ensure that the full exception and stacktrace are printed in the test results:

try {
    /* Tested code here... */
}
catch (Exception e) {
    throw new AssertionError("Exception was thrown.", e);
}

Sample output (using the same example code as the Assert.fail() example):

throwNewAssertionErrorTest(com.sandbox.SandboxTest)  Time elapsed: 0.002 sec  <<< FAILURE!
java.lang.AssertionError: Exception was thrown.
	at com.sandbox.SandboxTest.throwNewAssertionErrorTest(SandboxTest.java:22)
Caused by: java.lang.Exception: Exception 1
	at com.sandbox.SandboxTest.catchAndThrowNewException(SandboxTest.java:40)
	at com.sandbox.SandboxTest.throwNewAssertionErrorTest(SandboxTest.java:20)
Caused by: java.lang.Exception: Exception 0
	at com.sandbox.SandboxTest.throwNewException(SandboxTest.java:45)
	at com.sandbox.SandboxTest.catchAndThrowNewException(SandboxTest.java:38)
	at com.sandbox.SandboxTest.throwNewAssertionErrorTest(SandboxTest.java:20)

Much more information is provided when wrapping the original exception in an AssertionError. Having more relevant information makes problems easier to diagnose and fix. Don’t truncate the stacktraces of failing tests with Assert.fail(). Throw an AssertionError.

Comments

Related Posts

Programming Terms Cheat Sheet

Technical Writing

Version Control

Encapsulating Functionality

Step Through Your Code