领先一步
VMware提供培训和认证,以加速您的进步。
了解更多阅读时间:约6分钟 编码时间:约15分钟
如果您一直在关注这个系列,到目前为止,您应该已经构建了一个 Spring Boot 原型,它演示了RSocket 中存在的许多功能。但是,此代码不是生产代码;它是一个原型,是您 RSocket 之旅的垫脚石。对于生产代码,我希望所有通常的质量保证和测试规则都适用。因此,在本练习中,我将向您展示如何为 RSocket 响应程序编写集成测试,以便您可以更接近生产环境。
但首先,我所说的集成测试是什么意思?
在此上下文中,集成测试意味着测试 RSocket 请求者和响应程序之间来回的通信。在这样的测试期间,务必练习体系结构的每一层,包括网络。
但是,集成测试可能比常规单元测试更昂贵,正是因为您正在练习每一层。它们的运行时间可能更长,需要多个组件和层,并且可能更不可预测。但是,集成测试 还有其他好处,例如检查您的请求者和响应程序是否相互联系并正确通信。
您还会注意到,在本教程中我跳过了所有其他形式的测试。要涵盖所有可能的测试类型需要一整本书!如果您正在寻找有关测试 Spring Boot 应用程序的更一般介绍,请尝试观看 Andy Wilkinson 的此演讲,或查看Spring Boot 测试文档,或在线搜索“测试 Spring 应用程序”。
背景知识足够了;让我们开始测试吧!
如果您需要查看代码,可以在GitHub 上找到。如果您想了解本系列中其余文章的内容,它们都列在我的 Spring 网站页面上。
在您的 rsocket-server
项目中,在 /src/test/java/io/pivotal/rsocketserver/
文件夹中,创建一个名为 RSocketClientToServerITest
的新的集成测试类。最简单的方法通常是在您的 IDE 中。
建议的命名约定是使用后缀“ITest” 结束每个集成测试类名。生成的名称为 <您的类名>ITest.java
的文件名更容易阅读,并允许 Maven 过滤您的集成测试——您稍后将使用此技术。请务必使用 @SpringBootTest
注释您的新类,如下所示
@SpringBootTest
public class RSocketClientToServerITest {
// test code goes here
}
@SpringBootTest
注解允许 Spring Boot 为您的测试配置所有必需的内容,包括 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
值。
现在请求程序已就位;您可以添加第一个集成测试了。在此测试期间会发生两件事。首先,从请求程序到响应程序的调用,并附带命名路由和数据。其次,验证收到的响应是否完全符合预期。代码如下所示
@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 上的完整测试。
测试周期完成后,您可以关闭不再需要的任何资源。在本例中,这意味着释放 RSocket 请求程序。添加一个方法来执行此操作,并使用 @AfterAll
注释该方法,如下所示
@AfterAll
public static void tearDownOnce() {
requester.rsocket().dispose();
}
运行集成测试可能需要一段时间,并且它们可能因意外原因而失败,例如网络故障。因此,将集成测试隔离以便可以选择性地运行它们是有意义的。Maven 使用Failsafe 插件 来实现此目的。
要配置 failsafe,在您的 pom.xml
中,添加以下插件配置。此配置告诉 Maven 使用 failsafe 运行所有以后缀“ITest.java” 结尾的测试。它还告诉 Maven 将这些测试作为 integration-test
或 verify
生命周期阶段的一部分运行。
<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>
您现在可以在终端控制台中运行集成测试。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响应程序,您可以防止出现回归问题,检查组件是否正常通信,并以更大的信心将其交付给您的客户。