You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让执行失败的测试用例在构建层面判定为通过?

如何让执行失败的测试用例在构建层面判定为通过?

嘿,我完全懂你现在的困境!你要测试自己写的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 08:43:01