EmbeddedChannelを使ってNettyをテストする
1.はじめに
この記事では、
__EmbeddedChannel
__を使用して、インバウンドおよびアウトバウンドのチャネルハンドラの機能をテストする方法について説明します。
Netty
は高性能の非同期アプリケーションを書くための非常に用途の広いフレームワークです。このようなアプリケーションの単体テストは、適切なツールがないと難しい場合があります。
ありがたいことに、フレームワークは
_ EmbeddedChannel
classを提供しています – これは
ChannelHandlers_
のテストを容易にします。
2.セットアップ
__EmbeddedChannel
__はNettyフレームワークの一部なので、必要な唯一の依存関係はNetty自体の依存関係です。
依存はhttps://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22io.netty%22%20AND%20a%3A%22netty-all%22[Maven Centralで見つけることができます]:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.24.Final</version>
</dependency>
3.
__ EmbeddedChannel
__概要
-
_ EmbeddedChannel
クラスは
AbstractChannel _
** のもう1つの実装です – 実際のネットワーク接続を必要とせずにデータを転送します。
これは、インバウンドチャネルにデータを書き込むことでインバウンドメッセージをシミュレートし、アウトバウンドチャネルで生成された応答を確認することができるので便利です。これにより、チャネルパイプライン全体で各____ChannelHandlerを個別にテストできます。
1つ以上の
ChannelHandler
をテストするには、まず、コンストラクタの1つを使用して____EmbeddedChannelインスタンスを作成する必要があります。
__ChannelHandlersのリストをコンストラクタに渡すことで
__EmbeddedChannelを初期化する最も一般的な方法は次のとおりです。
EmbeddedChannel channel = new EmbeddedChannel(
new HttpMessageHandler(), new CalculatorOperationHandler());
ハンドラがパイプラインに挿入される順序をもっと制御したい場合は、デフォルトのコンストラクタで
EmbeddedChannel
を作成し、ハンドラを直接追加します。
channel.pipeline()
.addFirst(new HttpMessageHandler())
.addLast(new CalculatorOperationHandler());
また、**
EmbeddedChannelを作成すると、
DefaultChannelConfig
__クラスで指定されたデフォルト設定が使用されます。
デフォルトから接続タイムアウト値を減らすなど、カスタム設定を使用したい場合は、
__ config()
メソッドを使用して
ChannelConfig
__objectにアクセスできます。
DefaultChannelConfig channelConfig = (DefaultChannelConfig) channel
.config();
channelConfig.setConnectTimeoutMillis(500);
__EmbeddedChannel
には、
ChannelPipeline__へのデータの読み書きに使用できるメソッドが含まれています。最も一般的に使用されている方法は次のとおりです。
-
readInbound()
-
readOutbound()
-
writeInbound(Object … msgs)
-
writeOutbound(Object … msgs)
-
readメソッドは、インバウンド/アウトバウンドキューの最初の要素を取得して削除します。
** 要素を削除せずにメッセージのキュー全体にアクセスする必要がある場合は、
__ outboundMessages()
__methodを使用できます。
Object lastOutboundMessage = channel.readOutbound();
Queue<Object> allOutboundMessages = channel.outboundMessages();
-
Channelのインバウンド/アウトバウンドパイプラインへのメッセージの追加が成功した場合、writeメソッドは
__trueを返します
channel.writeInbound(httpRequest)
その考えは、out
__ChannelHandlers
__がそれらを処理するようにインバウンドパイプライン上にメッセージを書くということであり、アウトバウンドパイプラインから結果が読めることを期待しています。
4.
ChannelHandlers
をテストする
HTTPリクエストを受け取り、計算結果を含むHTTPレスポンスを期待する2つの____ChannelHandlerで構成されるパイプラインをテストする簡単な例を見てみましょう。
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は、インバウンドパイプライン内のすべての
__ChannelHandlerによって処理された後に送信されたデータに起因するメッセージです。
それでは、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.例外処理のテスト
別の一般的なテストシナリオは例外処理です。
__ChannelInboundHandlersで
exceptionCaught()メソッドを実装することで例外を処理できますが、例外を処理したくない場合があり、代わりにパイプラインの次の
ChannelHandler
__に渡します。
パイプラインで
__Throwable
objectが受信されたかどうかを確認し、それを再スローするために
EmbeddedChannel
クラスの
checkException()
__メソッドを使用できます。
このようにして
__Exception
をキャッチし、
ChannelHandler
__がそれをスローすべきでないかどうかをチェックすることができます。
assertThatThrownBy(() -> {
channel.pipeline().fireChannelRead(wrongHttpRequest);
channel.checkException();
}).isInstanceOf(UnsupportedOperationException.class)
.hasMessage("HTTP method not supported");
上記の例では、
Exception
が発生すると予想されるHTTPリクエストが送信されたことがわかります。
__checkException()
__methodを使用することで、パイプラインに存在する最後の例外を再スローできます。そのため、そこから必要なものをアサートできます。
5.まとめ
__EmbeddedChannelは、Nettyフレームワークによって提供されている
ChannelHandler
pipelineの正しさをテストするのに役立つ優れた機能です。これは各
__ChannelHandlerを個別にそしてより重要なことにはパイプライン全体をテストするために使用することができます。
この記事のソースコードはhttps://github.com/eugenp/tutorials/tree/master/libraries-server[GitHubで利用可能]です。