JUnit 5:如何在多个Quarkus集成测试前仅执行一次代码
实现Quarkus集成测试全局仅执行一次的初始化/清理代码
针对你遇到的跨@TestProfile测试类、需要全局仅执行一次初始化/清理代码的场景,以下是两种可靠的解决方案:
方案1:JUnit 5全局扩展(同JVM内生效)
如果你的测试在同一个JVM进程中运行(Maven/Gradle默认测试任务不fork的场景),可以自定义JUnit 5扩展,通过原子变量控制代码仅执行一次:
1. 编写全局扩展类(Kotlin)
import org.junit.jupiter.api.extension.BeforeAllCallback import org.junit.jupiter.api.extension.ExtensionContext import java.util.concurrent.atomic.AtomicBoolean class GlobalTestInitExtension : BeforeAllCallback { companion object { // 原子标记确保仅执行一次 private val hasRun = AtomicBoolean(false) } override fun beforeAll(context: ExtensionContext) { if (hasRun.compareAndSet(false, true)) { // 在这里编写你的全局初始化代码 println("全局初始化代码执行,仅一次") // 示例:初始化外部测试资源、预加载测试数据等 } } }
2. 注册扩展
有两种注册方式:
- 局部注册:在每个测试类上添加
@ExtendWith(GlobalTestInitExtension::class) - 全局注册:在
src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension文件中写入扩展类的全限定名(如com.yourpackage.GlobalTestInitExtension),所有JUnit 5测试会自动加载该扩展。
注意:如果测试配置了多进程fork(比如Maven Surefire的
forkCount>0),此方法会失效,需改用构建工具钩子。
方案2:构建工具生命周期钩子(跨进程生效)
如果测试存在进程fork,或需要绝对可靠的全局执行,直接利用Maven/Gradle的测试前后生命周期阶段:
Maven示例
在pom.xml中添加pre-integration-test和post-integration-test阶段任务:
<build> <plugins> <!-- 全局初始化任务 --> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.1.0</version> <executions> <execution> <id>global-test-init</id> <phase>pre-integration-test</phase> <goals> <goal>java</goal> </goals> <configuration> <mainClass>com.yourpackage.GlobalTestInitializer</mainClass> </configuration> </execution> <!-- 可选:全局清理任务 --> <execution> <id>global-test-cleanup</id> <phase>post-integration-test</phase> <goals> <goal>java</goal> </goals> <configuration> <mainClass>com.yourpackage.GlobalTestCleaner</mainClass> </configuration> </execution> </executions> </plugin> <!-- 配置集成测试执行 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> <version>3.1.2</version> <executions> <execution> <goals> <goal>integration-test</goal> <goal>verify</goal> </goals> <configuration> <groups>integration</groups> </configuration> </execution> </executions> </plugin> </plugins> </build>
编写初始化类:
class GlobalTestInitializer { @JvmStatic fun main(args: Array<String>) { // 全局初始化逻辑 println("Maven预集成测试阶段:全局初始化执行") } }
运行测试时执行mvn verify,会按「初始化→所有集成测试→清理」的顺序执行。
Gradle示例(Kotlin DSL)
在build.gradle.kts中添加:
// 配置集成测试 tasks.test { useJUnitPlatform() includeTags("integration") } // 全局初始化任务 val globalTestInit by tasks.registering(JavaExec::class) { mainClass.set("com.yourpackage.GlobalTestInitializer") classpath = sourceSets.test.get().runtimeClasspath } // 全局清理任务 val globalTestCleanup by tasks.registering(JavaExec::class) { mainClass.set("com.yourpackage.GlobalTestCleaner") classpath = sourceSets.test.get().runtimeClasspath } // 绑定任务依赖 tasks.test { dependsOn(globalTestInit) finalizedBy(globalTestCleanup) }
不推荐的方案:Quarkus启动事件
Quarkus的StartupEvent会在每个@TestProfile对应的应用实例启动时触发,不同Profile会重复执行,无法满足全局仅执行一次的需求,仅适合单一Profile的测试场景。
内容的提问来源于stack exchange,提问作者xxtesaxx
相关产品推荐
相关产品推荐

