在 Spring Boot 应用程序中分离集成测试

Posted

技术标签:

【中文标题】在 Spring Boot 应用程序中分离集成测试【英文标题】:Separating integration tests in spring boot app 【发布时间】:2020-04-29 20:18:27 【问题描述】:

我正在为 SpringBoot 应用程序编写测试。 我想将集成测试与单元测试分开。 现在我的项目结构如下所示:

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

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

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

我希望新的 integrationTest 模块与测试模块相同,但我不知道如何配置它。我设法将它添加为模块,将 integrationTest/java 目录标记为测试源根目录并在其中运行测试,但 @SpringBootTest 无法解析 ApplicationContext,并且我所有的 bean 始终为空。

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

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

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

【问题讨论】:

Gradle 用户手册有一节描述了如何做到这一点docs.gradle.org/current/userguide/…>。您可以使用 systemProperty("spring.profiles.active", "integration") 之类的东西在 integrationTest 任务定义中设置活动配置文件,尽管我猜如果集成和单元测试源是分开的,您实际上并不需要。感谢 baeldung.com/spring-profiles> 提到要设置的系统属性。 【参考方案1】:

您可以在其余测试中使用它们;应用 convention 并标记匹配以将它们过滤掉,例如将 IntegrationTest 附加到类名并为 JUnit @Tag 使用相同的值...然后只需定义/声明一些 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() 
    // ...
  

【讨论】:

【参考方案2】:

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

    src 下创建一个新目录(即src/integrationTest) 在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

    创建一个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+),整个过程似乎要简单得多,但由于它处于孵化状态,我没有使用它。

【讨论】:

以上是关于在 Spring Boot 应用程序中分离集成测试的主要内容,如果未能解决你的问题,请参考以下文章

如何从 springboot 应用程序中分离集成的 tomcat

如何使用注释在 testng + maven 中分离单元测试和集成测试?

使用 Eureka 服务集成测试 Spring Boot 服务

spring boot 集成测试(业务层)

基于spring-boot的应用程序的单元+集成测试方案

[翻译]Spring Boot 中的集成测试