RSocket 入门:测试 Spring Boot 响应器

工程 | Ben Wilcock | 2020 年 5 月 25 日 | ...

阅读时间:约 6 分钟 编码时间:约 15 分钟

如果您一直关注这个系列,那么现在您已经构建了一个 Spring Boot 原型,它展示了 RSocket 中的许多功能。然而,这段代码不是生产代码;它是一个原型,是您 RSocket 之旅的一个垫脚石。对于生产代码,我期望所有常规的质量保证和测试规则都适用。因此,在这个练习中,我将向您展示如何编写 RSocket 响应器的集成测试,以便您离生产更近一步。

但首先,我所说的集成测试是什么意思?

在这种上下文中,集成测试意味着测试 RSocket 请求者和响应者之间的双向通信。在这样的测试中,重要的是要锻炼架构的每一层,包括网络。

但是,集成测试可能比常规单元测试更昂贵,正是因为您锻炼了每一层。它们运行时间更长,需要多个组件和层,并且可能更不可预测。然而,集成测试还有其他好处,例如检查您的请求者和响应者是否相互联系并正确通信。

您还会注意到,在本教程中我跳过了所有其他形式的测试。要涵盖所有可能的测试类型,需要一整本书!如果您正在寻找 Spring Boot 应用程序测试的更一般性介绍,请尝试 Andy Wilkinson 的这次演讲,或者Spring Boot 测试文档,或者在线搜索“测试 Spring 应用程序”。

背景知识就足够了;让我们开始测试吧!

如果您需要查看代码,可以在GitHub上找到。如果您想了解本系列文章的其余部分,它们都列在 Spring 网站我的页面上。

步骤 1:创建集成测试

在您的 rsocket-server 项目中,在 /src/test/java/io/pivotal/rsocketserver/ 文件夹中,创建一个新的集成测试类 RSocketClientToServerITest。最简单的方法通常是在您的 IDE 中完成。

建议的命名约定是每个集成测试类名都以后缀 'ITest' 结尾。由此产生的文件名 <your-class-name>ITest.java 更易于阅读,并允许 Maven 过滤您的集成测试——您稍后将使用这项技术。请务必像这样用 @SpringBootTest 注解您的新类

@SpringBootTest
public class RSocketClientToServerITest {
  // test code goes here
}

@SpringBootTest 注解允许 Spring Boot 配置您测试所需的一切,包括 RSocket。它节省了大量时间和大量配置。

步骤 2:打开您的 RSocket 连接

您可以通过添加 RSocketRequester 作为全局类变量来为多个测试使用单个 RSocket 连接,如下所示

private static RSocketRequester requester;

在您的测试运行之前,您必须为这个请求者建立一个工作连接。JUnit5 中的 @BeforeAll 注解非常适合执行这些一次性设置任务。将以下方法添加到您的类中

    @BeforeAll
    public static void setupOnce(@Autowired RSocketRequester.Builder builder, @Value("${spring.rsocket.server.port}") Integer port) {
        requester = builder
                .connectTcp("localhost", port)
                .block();
    }

您会注意到方法签名期望 Spring Boot 从 Spring 应用程序上下文中传递一些项。RSocketRequester.Builder 简化了 RSocket 连接的创建,并且需要响应者的端口号来建立链接。端口号来自 application.properties 文件中的 spring.rsocket.server.port 值。

步骤 3:添加测试

现在请求者已就位;您已准备好添加第一个集成测试。在此测试期间发生两件事。首先,请求者向响应者发出调用,带有命名路由和附加数据。其次,验证收到的响应行为是否完全符合预期。代码如下所示

     @Test
     public void testRequestGetsResponse() {
         // Send a request message (1)
          Mono<Message> result = requester
                 .route("request-response")
                 .data(new Message("TEST", "Request"))
                 .retrieveMono(Message.class);
 
        // Verify that the response message contains the expected data (2)
        StepVerifier
                  .create(result)
                  .consumeNextWith(message -> { 
assertThat(message.getOrigin()).isEqualTo(RSocketController.SERVER); assertThat(message.getInteraction()).isEqualTo(RSocketController.RESPONSE);
assertThat(message.getIndex()).isEqualTo(0);})
                 .verifyComplete();
     }

在第一部分 (1) 中,使用的路由是 "request-response",数据是一个新的 Message 对象。来自响应者(您的 RSocketController)的结果是类型为 Message 的 Mono

在第二部分 (2) 中,StepVerifier 类检查 mono 的行为是否符合预期。在 consumeWithNext() 方法中,一个函数使用 AssertJ 的断言方法检查返回消息的内容。verifyComplete() 方法确保交互按预期完成。

其他交互的测试方式相同。这里不再赘述每种交互类型的测试,请查看 GitHub 上的完整测试。

步骤 4:关闭您的 RSocket 连接

一旦测试周期完成,您可以关闭不再需要的任何资源。在这种情况下,这意味着处理 RSocket 请求者。添加一个方法来执行此操作,并使用 @AfterAll 注解该方法,如下所示

      @AfterAll
      public static void tearDownOnce() {
          requester.rsocket().dispose();
      }

步骤 5:配置 Failsafe

运行集成测试可能需要一段时间,并且它们可能因意外原因(例如网络中断)而失败。因此,隔离您的集成测试以便您可以选择性地运行它们是很有意义的。Maven 使用 Failsafe 插件来实现这一点。

要配置 failsafe,请在您的 pom.xml 中添加以下插件配置。此配置告诉 Maven 使用 failsafe 运行所有以 'ITest.java' 后缀结尾的测试。它还告诉 Maven 在 integration-testverify 生命周期阶段运行这些测试。

<plugins>
<!-- other plugins -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>2.22.0</version>
        <executions>
          <execution>
            <goals>
              <goal>integration-test</goal>
              <goal>verify</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <includes>**/*ITest.java</includes>
        </configuration>
      </plugin>

您还需要防止集成测试与常规单元测试一起运行,因此添加以下 surefire 配置以将其排除

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
          <excludes>
            <exclude>**/*ITest.java</exclude>
          </excludes>
        </configuration>
      </plugin>
<!-- other plugins -->
</plugins>

步骤 6:运行您的测试

您现在可以在终端控制台中运行您的集成测试。Maven 使用 integration-test 目标来实现此目的。

./mvnw clean integration-test

Maven 现在运行您的集成测试,结果将显示在控制台中。

[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 23.582 s - in io.pivotal.rsocketserver.RSocketClientToServerITest
2020-05-19 10:43:27.512 INFO 39250 --- [extShutdownHook] i.p.rsocketserver.RSocketController : Detaching all remaining clients...
2020-05-19 10:43:27.513 INFO 39250 --- [extShutdownHook] i.p.rsocketserver.RSocketController : Shutting down.
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

更多内容!

您还可以集成测试客户端响应者。所需代码比上面略复杂。主要涉及创建一个虚假的请求者组件,其中包含与您在此处看到的类似的 StepVerifier 测试。我鼓励您查看源代码,而不是逐行描述代码。

最后思考

集成测试是产品生产路径上的关键组成部分。通过这种方式测试您的 RSocket 响应者,您可以防止回归,检查组件是否正常通信,并更自信地将它们交付给您的客户。

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看所有