There are benefits for either. Extending ExternalResource
it's convenient, especially if we only require a before()
to set something up.
However, we should be aware that, since the before()
method is executed outside of the try...finally
, any code that is required to do clean up in after()
won't get executed if there is an error during the execution of before()
.
This is how it looks inside ExternalResource
:
before();
try {
base.evaluate();
} finally {
after();
}
Obviously, if any exception is thrown in the test itself, or by another nested rule, the after will still get executed.
This is especially useful if we have a class that we want to extend in the rule. See example below for a more convenient method.
import org.junit.rules.TestRule; import org.junit.runners.model.Statement; public class AwesomeTestRule implements TextRule { @Override public Statement apply(Statement base, Description description) { return new AwesomeStatement(base); } private static class AwesomeStatement extends Statement { private Statement base; public AwesomeStatement(Statement base) { this.base = base; } @Override public void evaluate() throws Throwable { try { // do your magic base.evaluate(); // this will call Junit to run an individual test } finally { // undo the magic, if required } } } }
JUnit has an abstract implementation of @TestRule
that lets you write a rule in a more simpler way. This is called ExternalResource
and provides two protected methods that can be extended like this:
public class AwesomeTestRule extends ExternalResource { @Override protected void before() { // do your magic } @Override protected void after() { // undo your magic, if needed } }