views:

259

answers:

4

Almost all of my JUnit tests are written with the following signature:

public void testSomething() throws Exception

My reasoning is that I can focus on what I'm testing rather than exception handling which JUnit appears to give me for free. But am I missing anything by doing this? Is it against best practice? Would I gain anything by explicitly catching specific exceptions in my test and then fail()'ing on them?

+1  A: 

The main benefit involves when you are testing some scenario that requires an Exception to be thrown (e.g. err-r handling)

You can in JUnit4 use something like: @Test(expected=ArithmeticException.class) but some people find that to be harder to read/less intention revealing than an explicit try{} catch (Exception e) block, and if you wanted to check state (say of some mock object, or to see if the exception was thrown in the right place, or logged, or the like)

jayshao
A: 

If an exception is thrown, and you're not expecting it, the test should fail.

If it's an unchecked exception I allow the exception to be thrown and have JUnit fail the test.

If it's a checked exception, you have a choice: either add the exception to the throws clause of the method signature or catch it inside the method. The compiler will force a choice on you, because you can't run the code without either of these choices.

Lately I've tended to not catch exceptions inside my tests. If it's supposed to throw an exception, I mark it as such with the annotation. If it throws an unchecked exception, I left JUnit fail the test for me. If it's a checked exception, I add the throws clause to the method signature and left JUnit fail the test for me.

duffymo
Agreed that the test should fail, but my question is more about whether I should catch the exception and explicitly fail the test or let it bubble up to the JUnit framework and let it fail the test for me.
Chris Knight
+9  A: 

In general, if you are testing a case where you do not expect an Exception to occur, then I would just let the test method throw Exception as you have illustrated since it will nicely differentiate between Failing test cases (they do not pass one of your assertions) and Error test cases (they cause an unexpected Exception). The JUnit TestRunners will catch the thrown Exception regardless so you don't have to worry about your entire test suite bailing out if an Exception is thrown.

On the other hand, if you are writing a test that is supposed to trigger an exception, then you either want to use the @Test(expected=IllegalArgumentException.class) variant of the JUnit 4 annotation, or the more common JUnit 3 idiom of:

try {
  target.someMethodToTest();
  fail("Should have gotten an exception");
} catch (IllegalStateException ise) {
  //expected, it's all good
}
Ophidian
This is the best answer. I'll add that I think the question here is one of style: catch-and-fail, or throw? Normally, best practice avoids "throws Exception". The reason is that it makes exception handling meaningless for the API user. But there is no such user here. So "throws Exception" is the right practice.
Sean Owen
+4  A: 

Do NOT catch and fail -- you will lose valuable information. Let all exceptions fly right on out. This means you need to add each checked exception your signature that can be thrown. However, I'd advise you not to take the lazy way out and blindly use throws Exception as a matter of habit. This excuses you from ever even having to think about how your API really behaves with respect to exceptions.

Kevin Bourrillion
IMHO, adding the full list of checked exceptions to a test method does not provide much benefit, and in fact hampers the readability of your test signatures (especially if the SUT can throw a lot of exceptions).
Jacob