java 在@After 方法中检测 Junit 测试的失败或错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6981903/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Detect Failure or Error of Junit Test in @After method
提问by Ralph
Is there a way in JUnit to detect within an @After annotated method if there was a test failure or error in the test case?
如果测试用例中存在测试失败或错误,JUnit 是否有办法在 @After 注释的方法中进行检测?
One uglysolution would be something like that:
一种丑陋的解决方案是这样的:
boolean withoutFailure = false;
@Test
void test() {
...
asserts...
withoutFailure = true;
}
@After
public void tearDown() {
if(!withoutFailuere) {
this.dontReuseTestenvironmentForNextTest();
}
}
This is ugly because one need to take care of the "infrastructure" (withoutFailure flag) in the test code.
这是丑陋的,因为需要处理测试代码中的“基础设施”(没有Failure 标志)。
I hope that there is something where I can get the test status in the @After method!?
我希望有什么可以在@After 方法中获得测试状态的地方!?
采纳答案by dsaff
If you are lucky enough to be using JUnit 4.9 or later, TestWatcher
will do exactly what you want.
如果您有幸使用 JUnit 4.9 或更高版本,TestWatcher
将完全按照您的意愿行事。
Share and Enjoy!
分享和享受!
回答by Ralph
I extend dsaff's answer to solve the problem that a TestRule
can not execute some code snipped between the execution of the test-method and the after-method. So with a simple MethodRule
one can not use this rule to provide a success flag that is use in the @After
annotated methods.
我扩展了 dsaff 的答案,以解决TestRule
无法执行在 test-method 和 after-method 的执行之间截取的某些代码的问题。因此,MethodRule
不能使用简单的规则来提供在带@After
注释的方法中使用的成功标志。
My idea is a hack! Anyway, it is to use a TestRule
(extends TestWatcher
). A TestRule
will get knowledge about failed or success of a test. My TestRule
will then scan the class for all Methods annotated with my new AfterHack
annotations and invoke that methods with a success flag.
我的想法是一个黑客!反正就是用一个TestRule
(extends TestWatcher
)。ATestRule
将获得有关测试失败或成功的知识。TestRule
然后我将扫描类中所有用我的新AfterHack
注释注释的方法,并使用成功标志调用这些方法。
AfterHack
annotation
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
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<Method> getAfterHackMethods(Class<?> testClass) {
List<Method> results = new ArrayList<>();
for (Method method : testClass.getMethods()) {
if (method.isAnnotationPresent(AfterHack.class)) {
results.add(method);
}
}
return results;
}
}
Usage:
用法:
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) Hopefully there is a better solution in Junit5
- 2) The better way is to use the TestWatcher Rule instead of the @Before and @After Method at all (that is the way I read dsaff's answer)
- 1) 希望 Junit5 有更好的解决方案
- 2)更好的方法是使用 TestWatcher Rule 而不是 @Before 和 @After 方法(这是我阅读 dsaff 答案的方式)
@see
@看
回答by Tom Tresansky
I think what you'll want to do is add a RunListenerto the JUnit core. You can then override the testFailure
method to set your withoutFailure
flag in a single place so you can check it in your @After
annotated method.
我认为您要做的是向 JUnit 核心添加一个RunListener。然后,您可以覆盖该testFailure
方法以withoutFailure
在单个位置设置您的标志,以便您可以在带@After
注释的方法中检查它。
Also see: this blog postfor a discussion of some issues with this approach when using earlier versions of JUnit.
另请参阅:此博客文章讨论了使用早期版本的 JUnit 时这种方法的一些问题。
回答by Gustave
I don't know any easy or elegant way to detect the failure of a Junit test in an @After method.
我不知道在 @After 方法中检测 Junit 测试失败的任何简单或优雅的方法。
If it is possible to use a TestRule instead of an @After method, one possibility to do it is using two chained TestRules, using a TestWatcher as the inner rule.
如果可以使用 TestRule 而不是 @After 方法,一种可能性是使用两个链接的 TestRules,使用 TestWatcher 作为内部规则。
Example:
例子:
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(){
}
}