Based on Brett Walker's comment to this question, I was wondering how it can be done.
"If you want to fail the unit test, in the most general sense, when ever a catch clause is executed by the code in this method you are going to have to instrument the byte code to tell you when a catch clause is being executed. This is a complex task. I would not recommend this."
How would I test that some method has executed a catch clause? (the isCatched()
in the example below.
Let's say I have the following class:
public class A {
public void method() {
try {
// some code that may or may not throw an exception
} catch(Exception e) {
// do nothing
}
}
}
And then somewhere else:
public class CatchTester {
private A a;
public CatchTester(A a) {
this.a = a;
}
public boolean isCatched() {
// how to do this?
}
}
There are two approaches, both require knowledge of how to manipulate Java Byte codes. Tools such as ASM exist for making manipulating byte codes a little easier. One would then wire in a Java Agent or write a custom class loader that modified the class bytes as they were loaded into the JVM.
A very good example of this approach, is https://github.com/google/allocation-instrumenter. Allocation-Instrumenter modifies the byte codes of a class so that one can register a callback method that is called when ever a object allocation occurs. It is not much of a stretch to imagine a similar library for try/catch instrumentation.
If you want to detect via Instrumentation whether a certain code has been executed, you have to modify the code, injecting some sort of logging code which will effectively call back a method recording the fact that this code has been hit. Then you can check whether such a record exists right after the examined method returns.
While it wouldn’t be hard to insert such a logging code right at the beginning of each exception handler, there is the problem that on the byte code level, no distinction between catch
, finally
or try(…)
clauses is made. They all end up with defining exception handlers, some of them might re-throw catched exceptions. If you want to exclude handlers which re-throw exceptions, you would have to trace every possible code path, beginning at the exception handler’s entry, checking whether it ends in a normal completion or throws an exception, either the catched or another newly constructed one.
If you just want to know whether any catch
clause has been executed, the case is much simpler. If an exception has been thrown during method()
’s execution but method()
completes normally, i.e. the caller does not receive the exception, there must have been an exception handler executed.