EmbeddedChannelでNettyをテストする
1. 前書き
この記事では、EmbeddedChannel を使用して、インバウンドおよびアウトバウンドチャネルハンドラーの機能をテストする方法を説明します。
Nettyは、高性能の非同期アプリケーションを作成するための非常に用途の広いフレームワークです。 このようなアプリケーションの単体テストは、適切なツールなしでは難しい場合があります。
ありがたいことに、フレームワークはEmbeddedChannel class – which facilitates the testing of ChannelHandlersを提供してくれます。
2. セットアップ
EmbeddedChannelisはNettyフレームワークの一部であるため、必要な依存関係はNetty自体の依存関係のみです。
依存関係はMaven Centralにあります。
io.netty
netty-all
4.1.24.Final
3. EmbeddedChannelOverview
EmbeddedChannelclass is just another implementation of AbstractChannel –データwithout the need for a real network connectionを転送します。
これは、着信チャネルにデータを書き込むことで着信メッセージをシミュレートし、発信チャネルで生成された応答を確認できるため便利です。 このようにして、チャネルパイプライン全体の各ChannelHandler orを個別にテストできます。
1つ以上のChannelHandlersをテストするには、 weはまず、コンストラクターの1つを使用してEmbeddedChannel インスタンスを作成する必要があります。
ChannelHandlers のリストをコンストラクターに渡すことによってEmbeddedChannel isを初期化する最も一般的な方法:
EmbeddedChannel channel = new EmbeddedChannel(
new HttpMessageHandler(), new CalculatorOperationHandler());
ハンドラーがパイプラインに挿入される順序をより細かく制御したい場合は、デフォルトのコンストラクターを使用してEmbeddedChannelを作成し、ハンドラーを直接追加できます。
channel.pipeline()
.addFirst(new HttpMessageHandler())
.addLast(new CalculatorOperationHandler());
また、when we create an EmbeddedChannel, it’ll have a default configuration given by the DefaultChannelConfigclass.
接続タイムアウト値をデフォルト値から下げるなど、カスタム構成を使用する場合は、config()メソッドを使用してChannelConfig オブジェクトにアクセスできます。
DefaultChannelConfig channelConfig = (DefaultChannelConfig) channel
.config();
channelConfig.setConnectTimeoutMillis(500);
EmbeddedChannel には、ChannelPipelineへのデータの読み取りと書き込みに使用できるメソッドが含まれています。 最も一般的に使用される方法は次のとおりです。
-
readInbound()
-
readOutbound()
-
writeInbound(Object…msgs)
-
writeOutbound(Object…msgs)
The read methods retrieve and remove the first element in the inbound/outbound queue.要素を削除せずにメッセージのキュー全体にアクセスする必要がある場合は、outboundMessages() メソッドを使用できます。
Object lastOutboundMessage = channel.readOutbound();
Queue
メッセージがChannel:のインバウンド/アウトバウンドパイプラインに正常に追加された場合、書き込みメソッドはtrue を返します。
channel.writeInbound(httpRequest)
アイデアは、アウトChannelHandlersがメッセージを処理するようにインバウンドパイプラインにメッセージを書き込み、結果がアウトバウンドパイプラインから読み取れることを期待することです。
4. ChannelHandlersのテスト
HTTPリクエストを受信し、計算結果を含むHTTPレスポンスを期待する2つのChannelHandlers で構成されるパイプラインをテストする簡単な例を見てみましょう。
EmbeddedChannel channel = new EmbeddedChannel(
new HttpMessageHandler(), new CalculatorOperationHandler());
最初のHttpMessageHandler は、HTTPリクエストからデータを抽出し、それをパイプラインの秒ChannelHandler 、CalculatorOperationHandlerに渡して、データを処理します。
それでは、HTTPリクエストを作成して、インバウンドパイプラインがそれを処理するかどうかを確認しましょう。
FullHttpRequest httpRequest = new DefaultFullHttpRequest(
HttpVersion.HTTP_1_1, HttpMethod.GET, "/calculate?a=10&b=5");
httpRequest.headers().add("Operator", "Add");
assertThat(channel.writeInbound(httpRequest)).isTrue();
long inboundChannelResponse = channel.readInbound();
assertThat(inboundChannelResponse).isEqualTo(15);
writeInbound() メソッドを使用してインバウンドパイプラインでHTTPリクエストを送信し、readInbound()で結果を読み取ったことがわかります。 inboundChannelResponse isは、インバウンドパイプラインのすべてのChannelHandlers によって処理された後に送信されたデータから生じたメッセージです。
それでは、Nettyサーバーが正しいHTTP応答メッセージで応答するかどうかを確認しましょう。 これを行うには、アウトバウンドパイプラインにメッセージが存在するかどうかを確認します。
assertThat(channel.outboundMessages().size()).isEqualTo(1);
この場合のアウトバウンドメッセージはHTTP応答なので、内容が正しいかどうかを確認しましょう。 これを行うには、アウトバウンドパイプラインの最後のメッセージを読み取ります。
FullHttpResponse httpResponse = channel.readOutbound();
String httpResponseContent = httpResponse.content()
.toString(Charset.defaultCharset());
assertThat(httpResponseContent).isEqualTo("15");
4. 例外処理のテスト
別の一般的なテストシナリオは、例外処理です。
exceptionCaught() メソッドを実装することで、ChannelInboundHandlers で例外を処理できますが、例外を処理したくない場合があり、代わりに、例外を次のChannelHandlerに渡します。パイプライン。
EmbeddedChannelclassのcheckException() methodを使用して、パイプラインでThrowable objectが受信されたかどうかを確認し、それを再スローできます。
このようにして、Exception をキャッチし、ChannelHandlerがスローする必要があるかどうかを確認できます。
assertThatThrownBy(() -> {
channel.pipeline().fireChannelRead(wrongHttpRequest);
channel.checkException();
}).isInstanceOf(UnsupportedOperationException.class)
.hasMessage("HTTP method not supported");
上記の例では、Exceptionをトリガーする予定のHTTPリクエストを送信したことがわかります。 checkException() メソッドを使用することで、パイプラインに存在する最後の例外を再スローできるため、パイプラインから必要なものをアサートできます。
5. 結論
EmbeddedChannel は、Nettyフレームワークによって提供される優れた機能であり、ChannelHandler pipelineの正確性をテストするのに役立ちます。 これを使用して、各ChannelHandler を個別に、さらに重要なことにパイプライン全体をテストできます。
記事のソースコードはover on GitHubで入手できます。