RSS

gRPC JUnitテストでのクリーンアップを正常に行う

クライアントチャンネル、サーバー、および以前にアタッチされたコンテキストなどの gRPC リソースは、不要になったら常にクリーンアップすることがベストプラクティスです。

これは JUnit テストでも同様です。なぜなら、リソースがリークすると、マシンに永続的に残るだけでなく、後続のテストに干渉する可能性があるからです。それほど悪くないケースでは、前のテストからのリークしたリソースのために、後続のテストが合格できないことがあります。最悪のケースでは、以前合格したテストがリソースをリークしていなければ決して合格しなかったであろう後続のテストが合格してしまうことです。

したがって、クリーンアップ、クリーンアップ、クリーンアップ… そして、クリーンアップが成功しなかった場合はテストを失敗させましょう。

典型的な例は

public class MyTest {
  private Server server;
  private ManagedChannel channel;
  ...
  @After
  public void tearDown() throws InterruptedException {
    // assume channel and server are not null
    channel.shutdownNow();
    server.shutdownNow();
    // fail the test if cleanup is not successful
    assert channel.awaitTermination(5, TimeUnit.SECONDS) : "channel failed to shutdown";
    assert server.awaitTermination(5, TimeUnit.SECONDS) : "server failed to shutdown";
  }
  ...
}

よりグラフィカルにするには

public class MyTest {
  private Server server;
  private ManagedChannel channel;
  ...
  @After
  public void tearDown() throws InterruptedException {
    // assume channel and server are not null
    channel.shutdown();
    server.shutdown();
    // fail the test if cannot gracefully shutdown
    try {
      assert channel.awaitTermination(5, TimeUnit.SECONDS) : "channel cannot be gracefully shutdown";
      assert server.awaitTermination(5, TimeUnit.SECONDS) : "server cannot be gracefully shutdown";
    } finally {
      channel.shutdownNow();
      server.shutdownNow();
    }
  }
  ...
}

しかし、すべてのテストにこれを追加して、グラフィカルにシャットダウンさせるには、さらに作業が必要になります。なぜなら、シャットダウンの定型句を自分で書く必要があるからです。このため、gRPC テストライブラリには、この作業をより簡潔にするためのヘルパールールが用意されています。

当初、シャットダウンの定型句をなくすために、JUnit ルール GrpcServerRule が導入されました。このルールは、テストの開始時にインプロセスサーバーとチャンネルを作成し、テストの終了時にそれらを自動的にシャットダウンします。しかし、ユーザーはこのルールがインプロセス以外のトランスポート、サーバーへの複数のチャンネル、カスタムチャンネルまたはサーバービルダーオプション、および個々のテストメソッド内の設定をサポートしていないため、制限が厳しすぎると感じました。

より柔軟な JUnit ルールである GrpcCleanupRule が gRPC リリース v1.13 で導入され、これもシャットダウンの定型句をなくします。しかし、GrpcServerRule とは異なり、GrpcCleanupRule はサーバーやチャンネルを一切自動的に作成しません。ユーザーは、プレーンなテストと同様に、自分でサーバーを作成して起動し、自分でチャンネルを作成します。このルールを使用すると、ユーザーはテスト終了時にシャットダウンする必要があるすべてのリソース(チャンネルまたはサーバー)を登録するだけでよく、ルールがそれらを自動的にグラフィカルにシャットダウンします。

リソースは、テストメソッドを実行する前に登録できます

public class MyTest {
  @Rule
  public GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();
  ...
  private String serverName = InProcessServerBuilder.generateName();
  private Server server = grpcCleanup.register(InProcessServerBuilder
      .forName(serverName).directExecutor().addService(myServiceImpl).build().start());
  private ManagedChannel channel = grpcCleanup.register(InProcessChannelBuilder
      .forName(serverName).directExecutor().build());
  ...
}

または個々のテストメソッド内で登録できます

public class MyTest {
  @Rule
  public GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();
  ...
  private String serverName = InProcessServerBuilder.generateName();
  private InProcessServerBuilder serverBuilder = InProcessServerBuilder
      .forName(serverName).directExecutor();
  private InProcessChannelBuilder channelBuilder = InProcessChannelBuilder
      .forName(serverName).directExecutor();
  ...

  @Test
  public void testFooBar() {
    ...
    grpcCleanup.register(
    	serverBuilder.addService(myServiceImpl).build().start());
    ManagedChannel channel = grpcCleanup.register(
    	channelBuilder.maxInboundMessageSize(1024).build());
    ...
  }
}

これで、GrpcCleanupRule を使用すると、JUnit テストでの gRPC サーバーとチャンネルのグラフィカルなシャットダウンを心配する必要がなくなります。ぜひ試して、テストをクリーンアップしてください!