We use JUnit 3 at work and there is no ExpectedException
annotation. I wanted to add a utility to our code to wrap this:
try {
someCode();
fail("some error message");
} catch (SomeSpecificExceptionType ex) {
}
So I tried this:
public static class ExpectedExceptionUtility {
public static <T extends Exception> void checkForExpectedException(String message, ExpectedExceptionBlock<T> block) {
try {
block.exceptionThrowingCode();
fail(message);
} catch (T ex) {
}
}
}
However, Java cannot use generic exception types in a catch block, I think.
How can I do something like this, working around the Java limitation?
Is there a way to check that the ex
variable is of type T
?
Exception handling is used to handle the exceptions. We can use try catch block to protect the code. Catch block is used to catch all types of exception. The keyword “catch” is used to catch exceptions.
As you can see in the following code snippet, even if you know which exceptions the method might throw, you can't simply catch them. You need to catch the generic Exception class and then check the type of its cause. This code is not only cumbersome to implement, but it's also hard to read.
It refers to exception class that is near the top of the exception class hierarchy. Note that an exception class cannot be a generic class ... in the Java sense of generic types. The JLS says: "Note that a subclass of Throwable cannot be generic (§8.1.2)." -
Generics are not types. They are not templates. They are compile time type checks, in Java. Exception blocks catch on type. You can catch(Exception e) or even catch(Throwable e) and then cast as needed.
You could pass the Class object in and check that programatically.
public static <T extends Exception> void checkForException(String message,
Class<T> exceptionType, ExpectedExceptionBlock<T> block) {
try {
block.exceptionThrowingCode();
} catch (Exception ex) {
if ( exceptionType.isInstance(ex) ) {
return;
} else {
throw ex; //optional?
}
}
fail(message);
}
//...
checkForException("Expected an NPE", NullPointerException.class, //...
I'm not sure if you'd want the rethrow or not; rethrowing would equally fail/error the test but semantically I wouldn't, since it basically means "we didn't get the exception we expected" and so that represents a programming error, instead of a test environment error.
I understand the impulse to try to simplify your exception-test idiom, but seriously: don't. Every possible choice you'll come up with is a cure that's worse than the disease. Especially JUnit 4's @ExpectedException nonsense! It is a too-clever frameworky solution, requiring everyone to learn how it works, as opposed to a plain self-evident bit of regular Java code. Worse, it gives you no way to wrap only the part of your test that you expect to throw the exception, so if an earlier setup step throws that same exception, your test will pass even though your code is broken.
I could write a long diatribe about this here (I'm sorry for not having enough time to), as we've had a lengthy discussion of this issue among Java engineers here at Google, and the consensus was that none of these crazy solutions are worthwhile. Get used to try/catch, it's really not that bad.
Catch clause with type parameter is not possible:
http://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#cannotCatch
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