在JUnit中是否有办法在@After带注释的方法中检测测试用例中是否存在测试失败或错误?
一个丑陋的解决方案就是这样的:
boolean withoutFailure = false;
@Test
void test() {
...
asserts...
withoutFailure = true;
}
@After
public void tearDown() {
if(!withoutFailuere) {
this.dontReuseTestenvironmentForNextTest();
}
}
这很难看,因为需要在测试代码中处理“基础设施”(没有失败标志)。
我希望我能在@After方法中获得测试状态!
答案 0 :(得分:10)
如果您有幸使用JUnit 4.9或更高版本,TestWatcher
将完全按照您的意愿行事。
分享并享受!
答案 1 :(得分:3)
我扩展了dsaff的答案,以解决TestRule
无法在执行测试方法和后方法之间执行某些代码的问题。因此,使用简单的MethodRule
,不能使用此规则来提供在@After
带注释的方法中使用的成功标志。
我的想法是黑客!无论如何,它是使用TestRule
(扩展TestWatcher
)。 TestRule
将获得有关测试失败或成功的知识。然后,我的TestRule
将扫描该类以查找使用我的新AfterHack
注释注释的所有方法,并使用成功标记调用该方法。
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<Method> getAfterHackMethods(Class<?> testClass) {
List<Method> 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() {}
}
顺便说一句:
@see
答案 2 :(得分:2)
我认为您要做的是向JUnit核心添加RunListener。然后,您可以覆盖testFailure
方法,将withoutFailure
标记设置在一个位置,以便在@After
带注释的方法中进行检查。
另请参阅:this blog post,以便在使用早期版本的JUnit时讨论此方法的一些问题。
答案 3 :(得分:1)
我不知道在@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(){
}
}