如何使用不同配置两次运行JUnit 4测试
用最少改动实现多版本JUnit测试
既然你希望用最少代码改动来让所有现有测试在不同Storage.VERSION下运行,我推荐构建工具多轮执行+全局JUnit扩展的方案,现有测试代码完全不需要修改,只需要添加一个小扩展类和调整构建脚本即可。
方案一:构建工具多轮测试(改动最小)
步骤1:添加全局JUnit版本初始化扩展
这个扩展会在所有测试类运行前,根据系统属性设置Storage.VERSION,并且测试后恢复原值保证测试隔离:
import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.ExtensionContext; public class StorageVersionExtension implements BeforeAllCallback, AfterAllCallback { private int originalVersion; @Override public void beforeAll(ExtensionContext context) throws Exception { // 保存原始版本,测试后恢复 originalVersion = Storage.VERSION; // 读取系统属性,默认值为1 String versionProp = System.getProperty("storage.version", "1"); Storage.VERSION = Integer.parseInt(versionProp); } @Override public void afterAll(ExtensionContext context) throws Exception { // 恢复原始版本,避免影响其他测试 Storage.VERSION = originalVersion; } }
步骤2:让JUnit自动加载这个扩展
在src/test/resources/META-INF/services/目录下创建文件org.junit.jupiter.api.extension.Extension,内容是你的扩展类全限定名(比如com.yourpackage.StorageVersionExtension)。这样JUnit 5会自动全局应用这个扩展,所有测试类都会生效,不用修改现有测试代码。
步骤3:配置构建工具多轮执行测试
Maven配置(pom.xml)
修改maven-surefire-plugin,添加两次执行任务,分别设置不同的storage.version系统属性:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.1.2</version> <executions> <execution> <id>version-1-tests</id> <phase>test</phase> <configuration> <systemPropertyVariables> <storage.version>1</storage.version> </systemPropertyVariables> </configuration> </execution> <execution> <id>version-2-tests</id> <phase>test</phase> <configuration> <systemPropertyVariables> <storage.version>2</storage.version> </systemPropertyVariables> </configuration> </execution> </executions> </plugin> </plugins> </build>
Gradle配置(build.gradle)
注册两个测试任务,分别对应版本1和2,让默认test任务依赖它们:
test { // 定义要测试的版本列表 def versions = [1, 2] versions.each { version -> tasks.register("testVersion$version", Test) { systemProperty "storage.version", version testClassesDirs = sourceSets.test.output.classesDirs classpath = sourceSets.test.runtimeClasspath } } // 让默认test任务运行所有版本测试 dependsOn tasks.withType(Test).matching { it.name.startsWith('testVersion') } }
现在运行mvn test或者./gradlew test,就能自动用两个版本各跑一遍所有测试,完全不用改动现有测试类。
方案二:JUnit测试套件+参数化(一次运行多版本)
如果你希望在一次测试运行中,每个测试自动执行两次(对应两个版本),可以用JUnit 5的测试模板扩展,但需要少量修改测试方法:
- 创建一个版本提供扩展:
import org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestTemplateInvocationContext; import java.util.stream.Stream; public class StorageVersionProvider implements TestTemplateInvocationContextProvider { @Override public boolean supportsTestTemplate(ExtensionContext context) { return true; } @Override public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContexts(ExtensionContext context) { return Stream.of(1, 2).map(version -> new TestTemplateInvocationContext() { @Override public String getDisplayName(int invocationIndex) { return "Running with Storage.VERSION = " + version; } @Override public void beforeTest(ExtensionContext context) throws Exception { Storage.VERSION = version; } }); } }
- 在每个测试类上添加
@ExtendWith(StorageVersionProvider.class),并把测试方法的@Test改成@TestTemplate。这种方式需要修改每个测试类,但能在一次运行中完成所有版本测试。
注意事项
- 因为
Storage.VERSION是静态变量,一定要在测试后恢复原值,避免不同测试之间的干扰(方案一中的扩展已经处理了这个问题)。 - 如果用JUnit 4,把扩展换成带
@BeforeClass和@AfterClass的基类,让所有测试类继承即可,构建工具配置逻辑类似。
内容的提问来源于stack exchange,提问作者thatidiotguy
相关产品推荐
相关产品推荐

