如何让JUnit Enclosed测试仅显示一个父Runner并避免重复执行?
我之前也踩过这个坑!当用@RunWith(Enclosed.class)组织测试时,运行整个测试包经常会出现容器类被重复执行的情况——一次用Enclosed Runner成功跑内部测试,一次用默认Runner因为找不到测试方法报错。下面是几个经过验证的解决方案:
1. 把Enclosed容器类设为抽象类
Enclosed类本质只是个测试容器,本身不应该被当作可独立执行的测试类。给它加上abstract修饰符后,大多数测试运行器和IDE就不会把它单独拎出来执行了,只会通过Enclosed Runner去处理内部的静态测试类:
@RunWith(Enclosed.class) public abstract class MyEnclosedTestContainer { // 静态内部测试类,这里才放实际测试方法 public static class UserServiceTests { @Test public void testUserCreation() { // 测试逻辑 } } public static class OrderServiceTests { @Test public void testOrderPayment() { // 测试逻辑 } } }
同时要注意:容器类本身不要加@Test注解,也别继承TestCase这类测试基类,保持纯粹的容器角色。
2. 配置构建工具过滤测试类
如果用Maven或Gradle执行测试,可以通过插件配置明确指定只运行内部测试类,排除容器类本身:
Maven(surefire插件)
在pom.xml中添加过滤规则,只匹配Enclosed类内部的静态测试类($是Java内部类的类名分隔符):
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.1.2</version> <configuration> <includes> <include>**/*Tests$*.class</include> </includes> </configuration> </plugin> </plugins> </build>
Gradle
在build.gradle中给test任务添加过滤:
test { include '**/*Tests$*.class' }
3. 调整IDE的测试运行配置
以IntelliJ IDEA为例,配置包级测试时可以过滤掉Enclosed容器类:
- 打开包测试的运行配置
- 在「Test kind」选择「All in package」,然后在「Filters」中添加排除规则(比如
*EnclosedTestContainer) - 或者直接把「Test kind」设为「Tests in class」,手动选择所有内部测试类(不过这种方式不如抽象类省心)
4. 避免混合使用多个Runner注解
确保Enclosed容器类只标注@RunWith(Enclosed.class),不要同时加其他Runner注解(比如@RunWith(SpringRunner.class)),否则会导致测试运行器混淆,触发多次执行逻辑。
按上面的方法处理后,不管是单独运行Enclosed测试还是整个包,都会只通过Enclosed Runner执行一次内部测试类,不会再出现重复执行和报错的情况了。
内容的提问来源于stack exchange,提问作者Abhishek Tiwari

