同一JVM下用Surefire并发执行JUnit5测试却仅单线程运行的问题
问题:Maven Surefire插件并发测试仅单线程执行
我尝试通过Maven Surefire插件在同一JVM内并发执行测试,配置如下:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M7</version> <configuration> <systemPropertyVariables> <ut.forkNumber>${surefire.forkNumber}</ut.forkNumber> </systemPropertyVariables> <!--These values are chosen experimentally--> <argLine> -Xms512m -Xmx512m -XX:MaxDirectMemorySize=512m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError @{argLine} </argLine> <parallel>classes</parallel> <perCoreThreadCount>false</perCoreThreadCount> <threadCount>2</threadCount> <forkCount>1</forkCount> <reuseForks>true</reuseForks> </configuration> </plugin>
执行命令:
mvn test -Dorg.slf4j.simpleLogger.showThreadName=true
观察到所有测试类都在ThreadStreamConsumer线程中执行:
[ThreadedStreamConsumer] [INFO] Running com.spotnana.servicetests.profile.ProfileCreatePersonalUserTest ... [ThreadedStreamConsumer] [INFO] Running com.spotnana.servicetests.profile.PlanServiceTest
环境信息:
- JUnit版本:5.9.2
- Java版本:17
核心原因与修复方案
问题出在缺少JUnit Platform的并发执行支持配置,Surefire 3.x对JUnit 5的并行执行需要配合JUnit Platform的Provider和显式的并行启用参数,具体修复步骤如下:
1. 引入JUnit Platform Surefire Provider依赖
在Surefire插件中添加对应的Provider依赖,版本要和你的JUnit 5版本(5.9.2)匹配:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M7</version> <!-- 添加JUnit Platform Provider依赖 --> <dependencies> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-surefire-provider</artifactId> <version>1.9.2</version> </dependency> </dependencies> <configuration> <systemPropertyVariables> <ut.forkNumber>${surefire.forkNumber}</ut.forkNumber> <!-- 启用JUnit Platform并行执行 --> <junit.jupiter.execution.parallel.enabled>true</junit.jupiter.execution.parallel.enabled> <!-- 设置类级别的并发执行模式 --> <junit.jupiter.execution.parallel.mode.default>concurrent</junit.jupiter.execution.parallel.mode.default> <!-- 固定线程池大小为2 --> <junit.jupiter.execution.parallel.config.strategy>fixed</junit.jupiter.execution.parallel.config.strategy> <junit.jupiter.execution.parallel.config.fixed.parallelism>2</junit.jupiter.execution.parallel.config.fixed.parallelism> </systemPropertyVariables> <!-- 保留原有的JVM参数和Surefire配置 --> <argLine> -Xms512m -Xmx512m -XX:MaxDirectMemorySize=512m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError @{argLine} </argLine> <parallel>classes</parallel> <perCoreThreadCount>false</perCoreThreadCount> <threadCount>2</threadCount> <forkCount>1</forkCount> <reuseForks>true</reuseForks> </configuration> </plugin>
2. 替代配置方式(可选)
如果不想在pom.xml里加系统属性,也可以在src/test/resources下创建junit-platform.properties文件,写入以下内容:
junit.jupiter.execution.parallel.enabled = true junit.jupiter.execution.parallel.mode.default = concurrent junit.jupiter.execution.parallel.config.strategy = fixed junit.jupiter.execution.parallel.config.fixed.parallelism = 2
关键说明
你之前配置的<parallel>classes</parallel>是Surefire层面的并行开关,但对于JUnit 5来说,真正控制测试执行并行逻辑的是JUnit Platform的参数,必须同时启用这两部分配置,才能让测试类在多线程下运行。
内容的提问来源于stack exchange,提问作者tuk
相关产品推荐
相关产品推荐

