如何让执行失败的测试用例在构建层面判定为通过?
如何让执行失败的测试用例在构建层面判定为通过?
嘿,我完全懂你现在的困境!你要测试自己写的EdtExtension拦截器不会吞掉EDT里抛出的Throwable,特意写了个会主动抛出AssertionError的测试方法——可现在的问题是,这个测试执行时会失败,但从验证逻辑来说,这才是你想要的正确结果,你需要让构建工具把这种“执行失败”判定为测试通过,而且还不能用assertThrows()包裹异常,必须让异常真的从测试方法里抛出来。
咱们可以通过自定义JUnit扩展(或者规则,如果你用JUnit 4的话)来实现这个需求,核心思路就是:捕获测试方法抛出的异常,把它当作测试通过的标志;如果测试方法没抛出异常,反而主动抛出错误标记测试失败。
下面给你适配Java 8的具体实现方案:
方案一:JUnit 5 自定义扩展(适配你的@ExtendWith场景)
因为你代码里已经用了@ExtendWith,咱们可以写一个额外的扩展来处理这种特殊的测试用例:
import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.InvocationInterceptor; import org.junit.jupiter.api.extension.ReflectiveInvocationContext; import java.lang.reflect.Method; public class ExpectFailureAsSuccessExtension implements InvocationInterceptor { @Override public void interceptTestMethod(Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable { try { // 执行原测试方法 invocation.proceed(); // 如果走到这里,说明测试方法没抛异常——这才是出问题了! throw new AssertionError("测试方法未抛出异常,说明你的EDT拦截器吞掉了Throwable!"); } catch (AssertionError e) { // 捕获到了预期的异常,证明拦截器正常工作,测试通过 // 这里什么都不用做,JUnit会认为测试执行成功 } } }
然后把这个扩展加到你的测试类上,和原有的EdtExtension一起用:
@ExtendWith({EdtExtension.class, ExpectFailureAsSuccessExtension.class}) class AnnotatedPerMethod { @Test @EdtRun void ifThrowablesThrown_theyGetRethrown_notSwallowed() { assumeTrue(EventQueue.isDispatchThread()); throw new AssertionError(); } }
这样一来:
- 当测试方法抛出
AssertionError时,扩展会捕获它,JUnit会判定测试通过 - 如果哪天拦截器出问题吞了异常,测试方法没抛出错误,扩展会主动抛出错误,标记测试失败
方案二:JUnit 4 自定义TestRule(如果你用JUnit 4的话)
要是你还在使用JUnit 4,也可以用TestRule来实现同样的逻辑:
import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; public class ExpectFailureAsSuccessRule implements TestRule { @Override public Statement apply(Statement base, Description description) { return new Statement() { @Override public void evaluate() throws Throwable { try { base.evaluate(); // 测试方法没抛异常,标记失败 throw new AssertionError("测试方法未抛出异常,拦截器可能吞了Throwable!"); } catch (AssertionError e) { // 捕获到预期异常,测试通过 } } }; } }
使用的时候在测试类里加个Rule注解:
public class YourTestClass { @Rule public ExpectFailureAsSuccessRule failureRule = new ExpectFailureAsSuccessRule(); @Test void shouldPass_byFailing() { throw new AssertionError(); } }
针对你的简化MRE适配
把上面的扩展/规则加上后,你的简化测试用例:
@ExtendWith(ExpectFailureAsSuccessExtension.class) @Test void shouldPass_byFailing() { throw new AssertionError(); }
执行时会抛出异常,但构建工具会判定这个测试用例通过,完全符合你的要求。
内容来源于stack exchange
相关产品推荐
相关产品推荐

