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で利用可能]です。