在@After方法中检测Junit测试的失败或错误

如果测试用例中存在测试失败或错误,JUnit中是否有办法在@After带注释的方法中检测?

一个丑陋的解决方案是这样的:

boolean withoutFailure = false; @Test void test() { ... asserts... withoutFailure = true; } @After public void tearDown() { if(!withoutFailuere) { this.dontReuseTestenvironmentForNextTest(); } } 

这很难看,因为需要在测试代码中处理“基础结构”(withoutFailure标志)。

我希望有一些东西可以在@After方法中获得测试状态!?

如果您足够幸运使用JUnit 4.9或更高版本, TestWatcher将完全按照您的意愿执行操作。

分享和享受!

我扩展了dsaff的答案来解决TestRule无法在执行test-method和after-method之间执行某些代码的问题。 因此,使用简单的MethodRule不能使用此规则来提供在@After注释方法中使用的成功标志。

我的想法是一个黑客! 无论如何,它是使用TestRule (扩展TestWatcher )。 TestRule将获得有关测试失败或成功的知识。 然后,我的TestRule将扫描该类以查找使用我的新AfterHack注释注释的所有方法,并使用success标志调用该方法。


AfterHack注释

 import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(RUNTIME) @Target(METHOD) public @interface AfterHack {} 

AfterHackRule

 import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import org.junit.rules.TestWatcher; import org.junit.runner.Description; public class AfterHackRule extends TestWatcher { private Object testClassInstance; public AfterHackRule(final Object testClassInstance) { this.testClassInstance = testClassInstance; } protected void succeeded(Description description) { invokeAfterHackMethods(true); } protected void failed(Throwable e, Description description) { invokeAfterHackMethods(false); } public void invokeAfterHackMethods(boolean successFlag) { for (Method afterHackMethod : this.getAfterHackMethods(this.testClassInstance.getClass())) { try { afterHackMethod.invoke(this.testClassInstance, successFlag); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { throw new RuntimeException("error while invoking afterHackMethod " + afterHackMethod); } } } private List getAfterHackMethods(Class testClass) { List results = new ArrayList<>(); for (Method method : testClass.getMethods()) { if (method.isAnnotationPresent(AfterHack.class)) { results.add(method); } } return results; } } 

用法:

 public class DemoTest { @Rule public AfterHackRule afterHackRule = new AfterHackRule(this); @AfterHack public void after(boolean success) { System.out.println("afterHack:" + success); } @Test public void demofails() { Assert.fail(); } @Test public void demoSucceeds() {} } 

BTW:

  • 1)希望在Junit5中有更好的解决方案
  • 2)更好的方法是使用TestWatcher规则而不是@Before和@After方法(这是我阅读dsaff的答案的方式)

@看到

我想你要做的是将一个RunListener添加到JUnit核心。 然后,您可以覆盖testFailure方法,将withoutFailure标志设置在一个位置,以便在@After注释的方法中进行检查。

另请参阅: 此博客文章讨论了使用早期版本的JUnit时此方法的一些问题。

我不知道在@After方法中检测Junit测试失败的任何简单或优雅的方法。

如果可以使用TestRule而不是@After方法,则可以使用两个链式TestRules,使用TestWatcher作为内部规则。

例:

  package org.example; import static org.junit.Assert.fail; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExternalResource; import org.junit.rules.RuleChain; import org.junit.rules.TestRule; import org.junit.rules.TestWatcher; import org.junit.runner.Description; public class ExampleTest { private String name = ""; private boolean failed; @Rule public TestRule afterWithFailedInformation = RuleChain .outerRule(new ExternalResource(){ @Override protected void after() { System.out.println("Test "+name+" "+(failed?"failed":"finished")+"."); } }) .around(new TestWatcher(){ @Override protected void finished(Description description) { name = description.getDisplayName(); } @Override protected void failed(Throwable e, Description description) { failed = true; } }) ; @Test public void testSomething(){ fail(); } @Test public void testSomethingElse(){ } }