领先一步
VMware 提供培训和认证,以加速你的进步。
了解更多如果你的应用程序在运行时连接到一个RSocket服务器,该如何测试它呢?我们需要一种方法让测试启动一个服务器并告诉我们它监听的地址,然后我们需要能够注册请求和响应示例(又称“契约”)。这就是这个项目提供的功能——它就像 RSocket 的 Wiremock。
使用该项目最简单的方法是作为 JUnit (Jupiter) 扩展,例如:
@SpringBootTest
@ExtendWith(RSocketServerExtension.class)
class SocketsApplicationTests {
...
}
安装此扩展后,Spring Boot 测试将与一个 RSocket 服务器一起运行,该服务器监听由test.rsocket.server.port
指定的端口,因此测试可以直接连接到它,或者(更可能的是)它正在测试的代码将连接到它。你可能需要通过@SpringBootTest
注解告诉它连接的位置,例如,如果应用程序在运行时查找名为rsocket.port
的属性。
@SpringBootTest("rsocket.port=${test.rsocket.server.port}")
@ExtendWith(RSocketServerExtension.class)
class SocketsApplicationTests {
...
}
测试方法可以注入RSocketMessageCatalog
或RSocketMessageRegistry
,然后使用它们来设置或检查服务器的状态。默认情况下,服务器从类路径的/catalog/*.json
读取 JSON 契约,因此你可以在本地或在与服务器共享的测试库中设置这些契约。JSON 的结构反映了存储在RSocketMessageCatalog
中的MessageMapping
。这是一个示例(请求和响应只是 JSON 对象):
{
"pattern": "events.response.*",
"frameType": "REQUEST_RESPONSE",
"request": {
"origin": "Client"
},
"response": {
"origin": "Server",
"interaction": "Response",
"index": 0
}
}
此映射将匹配任何在与模式匹配的路由上的REQUEST_RESPONSE
帧类型,并且该路由还具有一个字段“origin”等于“Client”的请求。你还可以通过添加通配符来匹配请求中字段中的模式。或者你可以省略请求以仅根据路由匹配。如果帧类型是REQUEST_RESPONSE
,则响应是单值的。如果帧类型是REQUEST_STREAM
,则可以提供多值的“responses”,例如:
{
"pattern": "my.stream.route",
"frameType": "REQUEST_STREAM",
"responses": [
{
"origin": "Server",
"interaction": "Stream",
"index": 0
},
{
"origin": "Server",
"interaction": "Stream",
"index": 1
},
{
"origin": "Server",
"interaction": "Stream",
"index": 2
}
]
}
此外,你可以指定一个整数字段“repeat”来重复响应以形成更长的流。如果帧类型是REQUEST_FNF
,则没有响应,并且请求将被忽略。最后,如果帧类型是REQUEST_CHANNEL
,则映射 JSON 的格式与REQUEST_STREAM
相同,只是每次从输入流接收消息时,都会再次发出输出流。
如果你需要更灵活的处理规则,你可以从接口中的便捷静态工厂方法创建自己的MessageMapping
。你可以提供一个处理程序函数(除了触发并忘记的情况)、一个要匹配的模式,以及可选的要匹配的请求。这些方法可用于动态注册映射,以定义服务器在运行时的预期行为。
你可以通过从目录中获取MessageMapping
,然后调用其中一个drain()
方法来排出已接收的请求,从而检查服务器的状态。例如:
@SpringBootTest
@ExtendWith(RSocketServerExtension.class)
class DynamicRouteTests {
private RSocketRequester rsocketRequester;
public DynamicRouteTests(@Autowired RSocketRequester.Builder rsocketRequesterBuilder,
@Value("${test.rsocket.server.port:7000}") int port) {
rsocketRequester = rsocketRequesterBuilder.tcp("localhost", port);
}
@Test
void response(RSocketMessageRegistry catalog) {
MessageMapping response = MessageMapping.response("response")
.response(new Foo("Server", "Response"));
catalog.register(response);
assertThat(rsocketRequester.route("response").data(new Foo("Client", "Request"))
.retrieveMono(Foo.class).doOnNext(foo -> {
System.err.println(foo);
assertThat(foo.getOrigin()).isEqualTo("Server");
}).block()).isNotNull();
assertThat(response.drain()).hasSize(1);
assertThat(response.drain()).hasSize(0);
}
}
这里的代码仍然是一个原型,但它已经非常有用。所以请尝试一下并发送反馈,也许我们可以将其完善到可以发布的程度。