您需要扩展TestRule,尤其是apply()。例如,查看org.junit.rules.ExternalResource和org.junit.rules.TemporaryFolder。
ExternalResource看起来像这样:
public abstract class ExternalResource implements TestRule { public Statement apply(Statement base, Description description) { return statement(base); } private Statement statement(final Statement base) { return new Statement() { @Override public void evaluate() throws Throwable { before(); try { base.evaluate(); } finally { after(); } } }; } protected void before() throws Throwable { // do nothing } protected void after() { // do nothing }}然后,TemporaryFolder对此进行扩展,并实现before()和after()。
public class TemporaryFolder extends ExternalResource { private File folder; @Override protected void before() throws Throwable { // create the folder } @Override protected void after() { // delete the folder }因此,before在testMethod之前被调用,after在finally中被调用,但是您可以捕获并记录任何Exception,例如:
private Statement statement(final Statement base) { return new Statement() { @Override public void evaluate() throws Throwable { before(); try { base.evaluate(); } catch (Exception e) { log.error("caught Exception", e); } finally { after(); } } }; }编辑:以下工作:
public class SoTest { public class ExceptionLoggingRule implements TestRule { public Statement apply(Statement base, Description description) { return statement(base); } private Statement statement(final Statement base) { return new Statement() { @Override public void evaluate() throws Throwable { try { base.evaluate(); } catch (Exception e) { System.out.println("caught an exception"); e.printStackTrace(System.out); throw e; } } }; } } @Rule public ExceptionLoggingRule exceptionLoggingRule = new ExceptionLoggingRule(); @Rule public ExpectedException expectedException = ExpectedException.none(); @Test public void testMe() throws Exception { expectedException.expect(IOException.class); throw new IOException("here we are"); }}测试通过,您将获得以下输出:
caught an exceptionjava.io.IOException: here we are at uk.co.farwell.junit.SoTest.testMe(SoTest.java:40) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)...
规则的应用顺序是ExpectedException,它调用ExceptionLoggingRule,后者调用testMe方法。ExceptionLoggingRule捕获异常,将其记录并重新抛出,然后由ExpectedException处理。
如果只想记录意外的异常,只需切换规则的声明顺序即可:
@Rule public ExpectedException expectedException = ExpectedException.none(); @Rule public ExceptionLoggingRule exceptionLoggingRule = new ExceptionLoggingRule();
这样,将首先应用ExpectedException(即嵌套在exceptionLoggingRule中),并且仅重新引发意外的异常。此外,如果预期某些异常但未发生任何异常,则ExpectedException将抛出一个AssertionError,该异常也会被记录。
不能保证此评估顺序,但是除非您使用的是非常不同的JVM,或在Test类之间继承,否则它几乎不可能改变。
如果评估顺序很重要,那么您始终可以将一个规则传递给另一个规则进行评估。
编辑:使用最近发布的Junit 4.10,您可以使用@RuleChain正确地链接规则:
public static class UseRuleChain { @Rule public TestRule chain= RuleChain .outerRule(new LoggingRule("outer rule") .around(new LoggingRule("middle rule") .around(new LoggingRule("inner rule"); @Test public void example() {assertTrue(true); }}写日志
starting outer rulestarting middle rulestarting inner rulefinished inner rulefinished middle rulefinished outer rule



