如何拦截JUnit5中带有@Disabled注解的测试方法?
拦截JUnit5中@Disabled测试方法的解决方案
这个问题我之前也碰到过!确实,@Disabled标记的测试不会触发beforeTestExecution()这类执行阶段的回调——因为JUnit5会把它们直接标记为「跳过」,根本不会进入执行流程。不过有两种靠谱的方法可以拦截到这些禁用的测试,我给你详细说说:
方案1:使用DiscoveryListener(JUnit 5.7+版本适用)
如果你的JUnit5版本在5.7及以上,推荐用DiscoveryListener接口,它能在测试发现阶段就捕获到所有测试(包括禁用的),不用等到执行阶段。
实现示例
import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.discovery.DiscoveryListener; import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.jupiter.api.Disabled; import java.lang.reflect.Method; public class DisabledTestTrackingExtension implements DiscoveryListener { @Override public void testFound(TestDescriptor testDescriptor) { // 只处理测试方法级别的描述符 if (testDescriptor.getSource().isPresent() && testDescriptor.getSource().get() instanceof MethodSource) { MethodSource methodSource = (MethodSource) testDescriptor.getSource().get(); Method testMethod = methodSource.getJavaMethod().orElse(null); if (testMethod != null && testMethod.isAnnotationPresent(Disabled.class)) { // 这里写你要执行的操作,比如日志记录、统计等 System.out.println("发现禁用的测试方法: " + testMethod.getName()); } } } // 其他默认方法保持空实现即可,不需要额外重写 }
注册方式
- 局部注册:在需要监听的测试类上添加
@ExtendWith(DisabledTestTrackingExtension.class) - 全局注册:在
src/test/resources/junit-platform.properties中添加配置:junit.platform.discovery.listeners=com.yourpackage.DisabledTestTrackingExtension
方案2:使用TestExecutionListener(兼容更早JUnit5版本)
如果你还在使用5.7以下的版本,可以用TestExecutionListener的testSkipped()方法——所有被跳过的测试(包括@Disabled标记的)都会触发这个回调。
实现示例
import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.jupiter.api.Disabled; import java.lang.reflect.Method; import java.util.Optional; public class DisabledTestTrackingListener implements TestExecutionListener { @Override public void testSkipped(TestIdentifier testIdentifier, Throwable throwable) { // 提取测试方法的反射对象 Optional<Method> testMethod = testIdentifier.getSource() .filter(source -> source instanceof MethodSource) .map(source -> (MethodSource) source) .flatMap(MethodSource::getJavaMethod); testMethod.ifPresent(method -> { if (method.isAnnotationPresent(Disabled.class)) { // 执行你的自定义操作 System.out.println("检测到被跳过的禁用测试: " + method.getName()); } }); } // 其他方法可按需重写,默认空实现即可 }
注册方式
全局注册是最方便的,在src/test/resources/junit-platform.properties中添加:
junit.platform.launcher.listeners=com.yourpackage.DisabledTestTrackingListener
小提示
DiscoveryListener是在测试发现阶段触发,不管后续是否被其他条件过滤,都能捕捉到;而testSkipped()是在执行阶段触发,只有最终被跳过的测试才会触发。- 如果需要区分是
@Disabled导致的跳过还是其他条件(比如@EnabledOnJre不满足),直接检查方法上的@Disabled注解是最准确的方式。
内容的提问来源于stack exchange,提问作者Liviu Carausu
相关产品推荐
相关产品推荐

