補充上一篇的DEMO,包含RSC
的其他應用與測試的撰寫,測試是透過之前介紹過Reactor
提供的StepVerifier,還沒看過的人可以先去了解一下。
就用範例中的四種模式來說明,使用linux-base的朋友就麻煩再注意一下如何跳脫,這次範例是在windows環境下使用。
rsc tcp://localhost:8888 --route request-response --log --debug -d "{\""name\"":\""Robert\""}"
最熟悉如同http的模式。
rsc tcp://localhost:8888 --route fire-and-forget --log --debug -d "{\""name\"":\""Robert\""}"
不會有回傳。
rsc tcp://localhost:8888 --stream --route greetings --log --debug -d "{\""name\"":\""Robert\""}"
透過--stream
來告訴服務回傳也是stream,用來區分回傳是response還是stream。
rsc tcp://localhost:8888 --channel --route stream-stream --log --debug -d -
透過-channel
來判斷,-d
後的資料透過「-
(dash)」來不斷輸入資料,要注意這邊輸入的資料會直接傳送所以不需要再特別跳脫字元。{"name":"Robert"}
、{"name":"Jerry"}
四種互動方式的單元測試,先初始化RSocketRequester
,透過builder
與傳入的port
來建構requester
。LocalRSocketServerPort
:根據文件看起來是會去抓@Value("${local.rsocket.server.port}")
,推測是會自動偵測抓取本地啟動的rsocket server
的port,基本上就會等同於之前定義的spring.rsocket.server.port
。RSocketRequester
:輕量RSocket
Client,提供functional Api來建立連線、route
路徑與進行物件轉換。
private static RSocketRequester requester;
@BeforeAll
public static void setupOnce(@Autowired RSocketRequester.Builder builder,
@LocalRSocketServerPort Integer port) {
requester = builder
.tcp("localhost", port);
}
functional的測試可讀性很高,好像沒甚麼需要特別補充。
@Test
public void testRequestGetsResponse() {
Mono<GreetingResponse> response = requester
.route("request-response")
.data(new GreetingRequest("Robert"))
.retrieveMono(GreetingResponse.class);
StepVerifier
.create(response)
.consumeNextWith(message -> {
assertThat(message.getMessage()).isEqualTo("HelloRobert");
})
.verifyComplete();
}
@Test
public void testFireAndForget() {
Mono<Void> result = requester
.route("fire-and-forget")
.data(new GreetingRequest("Robert"))
.retrieveMono(Void.class);
StepVerifier
.create(result)
.verifyComplete();
}
RequestStream
、Channel
可以提前透過thenCancel()
來結束。
@Test
public void testRequestStream() {
Flux<GreetingResponse> stream = requester
.route("greetings")
.data(new GreetingRequest("Robert"))
.retrieveFlux(GreetingResponse.class);
StepVerifier
.create(stream)
.consumeNextWith(message -> {
assertThat(message.getMessage()).contains("HelloRobert");
})
.expectNextCount(0)
.consumeNextWith(message -> {
assertThat(message.getMessage()).contains("HelloRobert");
})
.thenCancel()
.verify();
}
@Test
public void testStreamGetsStream() {
Flux<GreetingRequest> just = Flux
.just(new GreetingRequest("Robert"), new GreetingRequest("Jerry"),
new GreetingRequest("Rhys"));
Flux<GreetingResponse> stream = requester
.route("stream-stream")
.data(just)
.retrieveFlux(GreetingResponse.class);
StepVerifier
.create(stream)
.consumeNextWith(message -> {
assertThat(message.getMessage()).isEqualTo("HelloRobert");
})
.consumeNextWith(message -> {
assertThat(message.getMessage()).isEqualTo("HelloJerry");
})
.thenCancel()
.verify();
}
##結語
因為不想爛尾還是補了一個part 2,終於30篇結束,之後應該會整理到個人blog裡面,其實還會有最後一篇心得文,讓之後想參加鐵人賽的人參考。
補一下之前文章的source code,但沒有很完整僅供參考。