You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 08:18:16