【问题标题】:End to end integration test for multiple spring boot applications under MavenMaven下多个spring boot应用的端到端集成测试
【发布时间】:2016-02-25 16:58:23
【问题描述】:

在Maven 构建的验证阶段,对多个Spring 引导应用程序运行端到端集成测试的推荐方法是什么?

基本上,我有一个多模块 Maven 项目,其中几个模块是独立的 Spring Boot 应用程序。这些独立的应用程序有自己的数据源配置、与JMS 队列的集成流等。例如,应用程序 A 将轮询数据库中的事件,当发生事件时,它会生成一个 JSON 数据文件并放入JMS 队列上的消息。应用程序 B 正在轮询 JMS 队列,因此获取消息,读取文件,使用另一个数据库进行一些处理,然后将消息放在不同的队列中。然后应用程序 C 将接收该消息等。

我已经为各个应用程序设置了集成测试;这些在 Maven 故障安全插件下运行。但是,我想在 Maven 下对整个系统进行端到端的集成测试。我在项目中设置了一个单独的模块专门用于此任务,因此希望此模块的验证构建阶段使用其他依赖模块进行端到端测试。

有没有这样做的最佳实践方法?我看到了 3 种可能的方式:

  1. 将每个应用程序的配置加载到相同的应用程序上下文中。但是,由于有多个数据源等,这会产生冲突,因此这些数据源都必须手动配置才能启用端到端集成测试 - 所以这对我来说似乎是错误的。
  2. 将每个应用程序作为一个单独的进程启动 - 那么如何正确跟踪它们并确保它们在测试模块构建停止/崩溃/等时关闭?
  3. 有没有办法在同一进程中轻松加载单独的 Spring Boot 应用程序,每个应用程序都有自己的配置上下文?这似乎是最明智的选择。关于Maven build/failsafe 插件是否有任何注意事项?

【问题讨论】:

标签: maven spring-boot integration-testing multi-module end-to-end


【解决方案1】:

只是跟进并说出我最终做了什么(继续运作良好):

  • 我在我的测试模块中创建了以下 Maven 配置文件:“default”默认跳过测试(我们使用 jgitflow 插件,因此只希望在明确请求时运行端到端测试),“standalone-e2e”用于不需要外部资源的端到端测试,例如数据库(针对想要进行完整端到端测试的开发人员),以及使用真实数据库等进行端到端测试的“集成 e2e”(可以作为 CI 的一部分被触发)。 Spring 配置文件(由相应的 Maven 配置文件激活)控制各个组件的配置。
  • 对于standalone-e2e,activemq-maven-plugin、hsqldb-maven-plugin 等相关插件作为端到端测试的一部分在使用build-helper-maven-plugin 保留的端口上运行(然后关闭)资源。 process-exec-maven-plugin 用于在预集成测试阶段启动所有要测试的组件(作为标准 Spring Boot 应用程序),并在集成测试后阶段自动关闭它们。 Spring 配置和特定的 Maven 测试依赖项负责其他资源,例如 a fake FTP server。在所有资源和组件运行后,测试代码本身会根据需要填充数据库和文件系统,并使用 JMS 触发流(并等待相应的回复等)。
  • integrated-e2e 配置文件几乎相同,但使用了在相关 Spring 属性中配置的“真实”外部资源(在我们的例子中是 Amazon SQS 队列、MySQL 数据库等)。
  • 测试所需和生成的所有文件(例如数据文件、HSQLDB 文件、日志文件等)都在“目标”构建目录下创建,因此很容易检查该区域以查看测试期间发生的情况,并允许“mvn clean”清除所有内容。

我希望这很有用 - 发现无论我需要做什么,都有一个 Maven 插件来处理它,这确实令人耳目一新!

【讨论】:

  • 感谢 Gary Sedgwick 提到 process-exec-maven-plugin 用于实现两个 spring-boot 应用程序交互的集成测试:stackoverflow.com/a/37397777/2745810
  • Gary,我正在尝试做一些非常相似的事情,只是增加了一点点:我正在尝试使用 Citrus 框架进行集成测试。我已经能够为我的服务设置集成测试,并为 SUT 使用的其他服务提供“模拟”。现在我正在尝试建立一个所有服务都是真实的端到端测试。
  • 我查看了 kmarabet 提供的关于 process-exec-maven-plugin(和其他 maven 插件)使用的信息,并试图看看我是否可以让它为我工作。我还在我的项目中创建了一个单独的 maven 模块,其唯一目的是包含和执行集成测试。我仍处于早期阶段,我正在弄清楚我需要做些什么来设置模块以按照我需要的方式运行,并遇到了 kmarabet 似乎已经解决的问题。
  • 当我运行 maven 构建时,IT 模块失败,因为 spring-boot-maven-plugin 想要进行“重新打包”并且找不到“主”类。好吧,没有主课。或者我应该说,可能有很多主要的测试类。不知道该怎么办。
  • 您能否简要描述一下您如何解决集成/系统测试问题以及您的 POM 文件和项目结构示例?
【解决方案2】:

非常好的问题!我自己会对其他人的回答感兴趣。我会分享我的意见。

根据我的理解,首先你应该知道你到底想测试什么。 集成测试应该至少与应用程序的一部分一起工作,并确保您开发的组件在半真实环境中正常工作。看起来你已经这样做了。

现在,关于系统测试(我有意区分集成测试和系统测试)。这些应该“模仿”质量检查人员:) 因此,他们将系统视为黑匣子。他们不能调用任何内部 API 并运行真实的流程。 端到端测试 IMO 属于这一类。

在这种情况下,您希望根据生产中部署的系统检查它们,并使用生产中的类路径。

所以我和你一样并不真正相信选项 1。

关于选项 3,我不确定它是否也是一个好的解决方案。 即使您使用不同的应用程序上下文运行您的东西(我不太了解 Spring boot,所以我无法从技术上评论它),据我了解,它们将在运行时共享相同的类路径,所以您可能有风险在你的第三方之间发生冲突(虽然我知道 spring boot 自己定义了很多版本的 jar,你知道我的意思),特别是当你只升级一个模块并且可能更改依赖项时。 因此,当您按照这种方法运行时,您并不真正知道内存中究竟运行了什么。

因此,对于 端到端 测试,我会选择选项 2。 关于同步,可能选择在应用程序级别实现一些逻辑,并在操作系统级别结合进程状态跟踪。 我想评论的另一点是,端到端测试通常仍然是功能测试(它们检查系统的功能行为),因此通常您不应该在每个测试中检查系统崩溃。如果您检查每个流的系统崩溃,这些测试将太慢。 当然,您可以维护一个相对较小的测试套件来检查极端情况。

希望对你有帮助

【讨论】:

    【解决方案3】:

    由于某些原因,我决定使用第二种方法并且有一个类似的问题要解决。我想出了maven-dependency-plugin 和process-exec-maven-plugin 的组合。

    所以假设我们有一些应用程序(例如app_A、app_B、...)和一个模块T,用于实现测试。

    这个想法是在开始测试之前将应用程序复制到本地构建目录并启动它们。测试运行后,应用程序将停止。

    为了实现这一点,我在模块 Ts pom 中添加了以下构建配置

    <build>
      ...
      <plugin>
        <!-- copy apps to current build-dir -->
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>3.1.2</version>
        <executions>
          <execution>
            <id>copy-app-A</id>
            <goals>
              <goal>copy</goal>
            </goals>
            <phase><!-- either pre-test or pre-integration-test --></phase>
            <configuration>
              <artifactItems>
                <artifactItem>
                  <groupId>${project.groupId}</groupId>
                  <artifactId>app_a</artifactId>
                  <version>${project.version}</version>
                  <outputDirectory>${project.build.directory}</outputDirectory>
                  <destFileName>app_a.jar</destFileName>
                </artifactItem>
              </artifactItems>
            </configuration>
          </execution>
          <execution><!-- repeat as many apps you have --></execution>
        </executions>
      </plugin>
      <plugin>
        <!-- start applications -->
        <groupId>com.bazaarvoice.maven.plugins</groupId>
        <artifactId>process-exec-maven-plugin</artifactId>
        <version>0.9</version>
        <executions>
          <execution>
            <!-- repeat 'start' block for each copied app -->
            <id>start-external-server</id>
            <phase><!-- same as in copy block --></phase>
            <goals>
              <goal>start</goal>
            </goals>
            <configuration>
              <name>run-app-A</name>
              <arguments>
                <argument>java</argument>
                <argument>-jar</argument>
                <argument>${project.build.directory}/app_a.jar</argument>
              </arguments>
            </configuration>
          </execution>
          <execution>
            <!-- this is always executed and ensures apps get stopped -->
            <id>stop-server</id>
            <phase><!-- either post-test or post-integration-test depending on --></phase>
            <goals>
              <goal>stop-all</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      ...
    </build>
    

    【讨论】:

    猜你喜欢
    • 2016-04-23
    • 1970-01-01
    • 2019-07-11
    • 1970-01-01
    • 2016-01-21
    • 2014-11-26
    • 2019-12-27
    • 2019-02-06
    • 2020-02-25
    相关资源
    最近更新 更多