web-dev-qa-db-ja.com

テストでCompletionExceptionをシミュレートする

HttpClientを返す関数を持つクラスCompletableFutureがあります。

public class HttpClient {

  public static CompletableFuture<int> getSize() {
      CompletableFuture<int> future = ClientHelper.getResults()
                 .thenApply((searchResults) -> {
                    return searchResults.size();
                });

      return future;
   }
}

次に、別の関数がこの関数を呼び出します。

public class Caller {

   public static void caller() throws Exception {
       // some other code than can throw an exception
       HttpClient.getSize()
       .thenApply((count) -> {
          System.out.println(count);
          return count;
       })
       .exceptionally(ex -> {
          System.out.println("Whoops! Something happened....");
       });
   }
}

さて、それをシミュレートするテストを書きたいと思いますClientHelper.getResultsfailsなので、私はこれを書きました:

@Test
public void myTest() {
    HttpClient mockClient = mock(HttpClient.class);

    try {
        Mockito.doThrow(new CompletionException(new Exception("HTTP call failed")))
                .when(mockClient)
                .getSize();

        Caller.caller();

    } catch (Exception e) {
        Assert.fail("Caller should not have thrown an exception!");
    }
}

このテストは失敗します。 exceptionally内のコードは実行されません。ただし、ソースコードを正常に実行しても、HTTP呼び出しが失敗した場合は、exceptionallyブロックに問題なく移動します。

exceptionallyコードが実行されるようにテストを作成するにはどうすればよいですか?

13

テストでこれを行うことで、これを機能させることができました。

CompletableFuture<Long> future = new CompletableFuture<>();
future.completeExceptionally(new Exception("HTTP call failed!"));

Mockito.when(mockClient.getSize())
        .thenReturn(future);

しかし、これが最善の方法かどうかはわかりません。

12