在测试中模拟CompletionException

Mar*_*ari 12 java exception mockito completable-future

我有一个HttpClient具有返回功能的类CompletableFuture:

public class HttpClient {

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

      return future;
   }
}
Run Code Online (Sandbox Code Playgroud)

然后另一个函数调用此函数:

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....");
       });
   }
}
Run Code Online (Sandbox Code Playgroud)

现在,我想写一个测试来模拟ClientHelper.getResults 失败,所以我写了这个:

@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!");
    }
}
Run Code Online (Sandbox Code Playgroud)

此测试失败.exceptionally永远不会执行代码.但是,如果我正常运行源代码并且HTTP调用失败,它就会exceptionally很好地进入块.

我该如何编写测试以便exceptionally执行代码?

Mar*_*ari 15

我在测试中通过这样做来实现这个目的:

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

Mockito.when(mockClient.getSize())
        .thenReturn(future);
Run Code Online (Sandbox Code Playgroud)

不知道这是不是最好的方法.

  • 我认为这是最好的方法:CompletableFuture是一个广泛使用且经过良好测试的库,因此您可以依赖它来测试代码,而不是尝试使用Mockito复制其行为.(当然,Mockito是一种很好的方式,可以在你的模拟系统中提供Future.) (2认同)