Gradle Test Suite集成测试无法获取部分项目依赖问题排查
Gradle 8.3 + Spring Boot集成测试依赖访问问题
问题现象
使用Gradle 8.3和Spring Boot搭建测试套件时,集成测试无法访问部分包,例如:
import kotlinx.coroutines.runBlocking import org.springframework.data
但普通测试可以正常访问这些包。同时,集成测试能正常访问其他包,比如:
import com.mycompany.backend.foo import org.springframework.beans.factory.annotation.Autowired import org.springframework.security.access.AccessDeniedException
原本以为configureEach块中的implementation(project())配置能让集成测试获取到所需依赖,但实际并未生效,求问题原因及解决办法。
当前测试配置代码
testing { suites { val test by getting(JvmTestSuite::class) { targets { all { testTask.configure { finalizedBy(tasks.jacocoTestReport) filter { isFailOnNoMatchingTests = false excludeTestsMatching("*Integration*Test") excludeTestsMatching("*.integration.*") } } } } } configureEach { if (this is JvmTestSuite) { useJUnitJupiter() dependencies { implementation(project()) implementation(project(":my-testutils")) } targets { all { testTask.configure { minHeapSize = "512m" maxHeapSize = "2G" } } } } } register<JvmTestSuite>("integrationTest") { targets { sources { kotlin { setSrcDirs(listOf("src/testIntegration/kotlin")) } } all { testTask.configure { shouldRunAfter(test) finalizedBy(tasks.jacocoTestReport) filter { isFailOnNoMatchingTests = false includeTestsMatching("*.integration.*") includeTestsMatching("*IntegrationTest") } } } } } } }
问题原因
核心问题是Gradle容器的configureEach方法执行顺序与套件注册顺序不匹配:
configureEach仅会对调用它时已经存在的测试套件应用配置,后续注册的新套件不会自动触发该配置块。- 你的代码中,
configureEach是在注册integrationTest之前调用的,因此这个新的集成测试套件没有被configureEach处理,也就没有添加implementation(project())等依赖配置,导致无法访问相关包。 - 普通测试的
test套件是Gradle默认创建的,在调用configureEach时已经存在,所以能正常获取到依赖。
解决方案
有三种可行的解决方式,选其中一种即可:
方式一:改用whenObjectAdded监听新套件
将configureEach替换为whenObjectAdded,它会对当前及未来所有添加的测试套件应用配置,无需在意注册顺序:
testing { suites { val test by getting(JvmTestSuite::class) { targets { all { testTask.configure { finalizedBy(tasks.jacocoTestReport) filter { isFailOnNoMatchingTests = false excludeTestsMatching("*Integration*Test") excludeTestsMatching("*.integration.*") } } } } } // 替换configureEach为whenObjectAdded whenObjectAdded { if (this is JvmTestSuite) { useJUnitJupiter() dependencies { implementation(project()) implementation(project(":my-testutils")) } targets { all { testTask.configure { minHeapSize = "512m" maxHeapSize = "2G" } } } } } register<JvmTestSuite>("integrationTest") { targets { sources { kotlin { setSrcDirs(listOf("src/testIntegration/kotlin")) } } all { testTask.configure { shouldRunAfter(test) finalizedBy(tasks.jacocoTestReport) filter { isFailOnNoMatchingTests = false includeTestsMatching("*.integration.*") includeTestsMatching("*IntegrationTest") } } } } } } }
方式二:在集成测试套件中显式配置依赖
直接在注册integrationTest时添加依赖配置,确保它能获取到所需依赖:
register<JvmTestSuite>("integrationTest") { // 显式添加通用配置 useJUnitJupiter() dependencies { implementation(project()) implementation(project(":my-testutils")) } targets { sources { kotlin { setSrcDirs(listOf("src/testIntegration/kotlin")) } } all { testTask.configure { minHeapSize = "512m" maxHeapSize = "2G" shouldRunAfter(test) finalizedBy(tasks.jacocoTestReport) filter { isFailOnNoMatchingTests = false includeTestsMatching("*.integration.*") includeTestsMatching("*IntegrationTest") } } } } }
方式三:调整顺序,先注册所有套件再调用configureEach
把所有套件的注册放在configureEach之前,确保所有套件都能被配置:
testing { suites { val test by getting(JvmTestSuite::class) { targets { all { testTask.configure { finalizedBy(tasks.jacocoTestReport) filter { isFailOnNoMatchingTests = false excludeTestsMatching("*Integration*Test") excludeTestsMatching("*.integration.*") } } } } } // 先注册集成测试套件 register<JvmTestSuite>("integrationTest") { targets { sources { kotlin { setSrcDirs(listOf("src/testIntegration/kotlin")) } } all { testTask.configure { shouldRunAfter(test) finalizedBy(tasks.jacocoTestReport) filter { isFailOnNoMatchingTests = false includeTestsMatching("*.integration.*") includeTestsMatching("*IntegrationTest") } } } } } // 现在所有套件都已存在,调用configureEach统一配置 configureEach { if (this is JvmTestSuite) { useJUnitJupiter() dependencies { implementation(project()) implementation(project(":my-testutils")) } targets { all { testTask.configure { minHeapSize = "512m" maxHeapSize = "2G" } } } } } } }
内容的提问来源于stack exchange,提问作者Stuck
相关产品推荐
相关产品推荐

