If I write test cases for a function that throws a bunch of exceptions should I add a throws declaration for these exceptions in my test method or should I catch each individual exception. What is the correct way of going about it? I believe try-catch is a better way but in the catch block should I print the stacktrace?
For example, I have a method getGroups(String name)
that throws AuthenticationException
. If I write a test case to check if an IllegalArgumentException
is being thrown when the name
parameter is null, how do I handle the AuthenticationException
? Do I add it to throws part of my method or should I enclose the exception in a try-catch
block.
@Test
public void testGetGroupsWithNull() throws AuthenticationException {
thrown.expect(IllegalArgumentException.class);
getGroups(null);
}
In the above test case I just added a throws AuthenticationException
, but I would like to know if it is better to enclose the exception in a try-catch block and what shoudld I do after catching the exception. I could print the stack trace.
I am handling the unexpected exception AuthenticationException
by not placing it in the 'throws' clause but in a try/catch block.
@Test
public void testGetGroupsWithNull() {
thrown.expect(IllegalArgumentException.class);
try {
getGroups(null);
} catch(AuthenticationExcption e) {
Assert.fail("Authentication Exception");
}
}
JUnit has a great article here: https://github.com/junit-team/junit/wiki/Exception-testing on this very subject. You can do:
@Test(expected= IndexOutOfBoundsException.class)
public void empty() {
new ArrayList<Object>().get(0);
}
or:
@Test
public void testExceptionMessage() {
try {
new ArrayList<Object>().get(0);
fail("Expected an IndexOutOfBoundsException to be thrown");
} catch (IndexOutOfBoundsException anIndexOutOfBoundsException) {
assertThat(anIndexOutOfBoundsException.getMessage(), is("Index: 0, Size: 0"));
}
}
If a JUnit test throws an unexpected exception, it fails. That is the behaviour that you want. So there's no point in EVER using a try/catch block. If you're expecting an exception, use an ExpectedException rule (which you obviously know about, from your code snippet). But whether you're expecting one or not, don't use try/catch.
This means that if your exception is a checked exception, you need a throws clause. In fact, you'll often need a throws clause on your test method, even when you're NOT expecting the exception to be thrown, just because your test calls a method that can SOMETIMES throw a checked exception. I have got into the habit of writing throws Exception
on every single test method. There is no reason not to; and it's just one less thing to worry about.
The annotation is more communicative.
It signals what the test expects to happen without forcing the reader to read the code.
Any single test should only expect a single exception to be thrown, because each test should be testing a single behavior. A single behavior can only throw one exception.
If any other exception is thrown it's a test failure. The test method signature must reflect any possible checked exceptions, of course, as would real code calling that same method.
Using the rule of writing as little code as possible to solve the problem, your first code snippet wins. So yes, put the AuthenticationException
into your test method's throws
clause. It is more succinct and readable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With