How to use JUnit 4 to test some code to throw exceptions?
Although I can certainly do such things:
@Test public void testFooThrowsIndexOutOfBoundsException() { boolean thrown = false; try { foo.doStuff(); } catch (IndexOutOfBoundsException e) { thrown = true; } assertTrue(thrown); }
I remember in this case, having an annotation or an asset.xyz or something less cluttered is the essence of JUnit.
#1 building
I've tried a lot of methods here, but they're either complicated or they don't exactly meet my requirements. In fact, you can simply write a helper method:
public class ExceptionAssertions { public static void assertException(BlastContainer blastContainer ) { boolean caughtException = false; try { blastContainer.test(); } catch( Exception e ) { caughtException = true; } if( !caughtException ) { throw new AssertionFailedError("exception expected to be thrown, but was not"); } } public static interface BlastContainer { public void test() throws Exception; } }
Use it like this:
assertException(new BlastContainer() { @Override public void test() throws Exception { doSomethingThatShouldExceptHere(); } });
Zero dependency: no simulation, no powermock; and works well on the final course.
#2 building
What to do: catch a very common exception, make sure it leaves the catch block, and then assert that the exception's class is the exception you expect. If a) the exception is of the wrong type (for example, if you use a Null pointer instead), and b) never throws an exception, the assertion fails.
public void testFooThrowsIndexOutOfBoundsException() { Throwable e = null; try { foo.doStuff(); } catch (Throwable ex) { e = ex; } assertTrue(e instanceof IndexOutOfBoundsException); }
#3 building
JUnit has built-in support for this with "expected" attribute
#4 building
JUnit 4 supports this:
@Test(expected = IndexOutOfBoundsException.class) public void testIndexOutOfBoundsException() { ArrayList emptyList = new ArrayList(); Object o = emptyList.get(0); }
Reference resources:
#5 building
Be careful when using the expected exception because it only asserts that the method threw the exception, not a specific line of code in the test.
I tend to use it for test parameter validation because such methods are usually very simple, but it is better to use more complex tests for:
try { methodThatShouldThrow(); fail( "My method didn't throw when I expected it to" ); } catch (MyException expectedException) { }
Use judgment.