Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should jUnit test cases handle default exceptions in a throws declaration or in a try catch block

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 AuthenticationExceptionby 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");
}
}
like image 209
user12222 Avatar asked Aug 14 '13 22:08

user12222


4 Answers

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"));
      }
  }
like image 61
Jim Barrows Avatar answered Oct 06 '22 05:10

Jim Barrows


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.

like image 39
Dawood ibn Kareem Avatar answered Oct 06 '22 06:10

Dawood ibn Kareem


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.

like image 31
Dave Newton Avatar answered Oct 06 '22 06:10

Dave Newton


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.

like image 37
Kkkev Avatar answered Oct 06 '22 05:10

Kkkev