在 spring 引导应用程序中分离集成测试

Separating integration tests in spring boot app

我正在为 SpringBoot 应用程序编写测试。 我想将集成测试与单元测试分开。 现在我的项目结构看起来像这样:

├── Demo
│   ├── src
│   │   ├── main
|   |   |   └──java
│   │   ├── test
|   |   |   └──java

有没有办法添加这样的模块:

├── Demo
│   ├── src
│   │   ├── main
|   |   |   └──java
│   │   ├── integrationTest
|   |   |   └──java
│   │   ├── test
|   |   |   └──java

我希望新的 integrationTest 模块能像测试模块一样工作,但我不知道如何配置它。我设法将它添加为模块,将 integrationTest/java 目录标记为 Test Sources Root 并在其中进行 运行 测试,但 @SpringBootTest 无法解析 ApplicationContext,并且我的所有 bean 始终为空。

当我在测试模块中编写相同的测试时,它工作正常。

有办法吗? 这是分离集成测试的正确方法吗? 如果不是,最佳做法是什么?

我在 intelliJ 工作,我使用 gradle 作为包管理器。

您可以将它们与其余测试一起使用;应用 约定 和标签匹配以过滤掉它们,例如将 IntegrationTest 附加到 class 名称并为 JUnit 使用相同的值@Tag...然后 define/declare 一些 Gradle 任务来执行它们:

test {
  useJUnitPlatform()
}

task integrationTests(type: Test) {
  filter { includes = ["IntegrationTest"] }
  useJUnitPlatform()
}

task unitTests(type: Test) {
  filter { includes = ["UnitTest"] }
  useJUnitPlatform()
}

完整示例:

package tld.domain.support;

public final class Category {
  public static final INTEGRATION_TEST = "IntegrationTest";

  public static final UNIT_TEST = "UnitTest";
}
import tld.domain.support.Category;

import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

@Tag(Category.INTEGRATION_TEST)
final class MyIntegrationTest {
  @Test
  void testFoo() {
    // ...
  }

根据@iboisver 的评论,您可以将它们分开,我们鼓励您在 gradle docs 中这样做。您基本上必须:

  1. src 下创建一个新目录(即 src/integrationTest
  2. build.gradle 文件中添加源集及其配置:
sourceSets {
    integrationTest {
        compileClasspath += sourceSets.main.output + sourceSets.test.output
        runtimeClasspath += sourceSets.main.output + sourceSets.test.output
    }
}

configurations {
    integrationTestImplementation.extendsFrom testImplementation
    integrationTestRuntimeOnly.extendsFrom testRuntime
}
  1. 为 运行 集成测试创建一个 integrationTests 任务,并将其附加到 check 任务(也在 build.gradle 中):
task integrationTest(type: Test) {
    description = 'Runs integration tests.'
    group = 'verification'

    testClassesDirs = sourceSets.integrationTest.output.classesDirs
    classpath = sourceSets.integrationTest.runtimeClasspath
    shouldRunAfter test
}

check.dependsOn integrationTest

我找到了几篇非常有用的文章 (1, 2),它们指导我进行自己的集成测试设置。

注意:如果您使用 JVM Test Suite Plugin(需要 Gradle 7.3+),整个过程似乎要简单得多,但由于它处于孵化状态,我没有接受它。