【问题标题】:Simulate CompletionException in a test在测试中模拟 CompletionException
【发布时间】:2018-01-21 06:12:29
【问题描述】:

我有一个类 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.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!");
    }
}

此测试失败。 exceptionally 中的代码永远不会被执行。但是,如果我正常运行源代码并且 HTTP 调用确实失败了,它会转到 exceptionally 块就好了。

我必须如何编写测试才能执行exceptionally 代码?

【问题讨论】:

    标签: java exception mockito completable-future


    【解决方案1】:

    我在测试中这样做了:

    CompletableFuture<Long> future = new CompletableFuture<>();
    future.completeExceptionally(new Exception("HTTP call failed!"));
    
    Mockito.when(mockClient.getSize())
            .thenReturn(future);
    

    不确定这是否是最好的方法。

    【讨论】:

    • 我认为这是最好的方法:CompletableFuture 是一个广泛使用且经过良好测试的库,因此您可以依赖它来测试您的代码,而不是尝试使用 Mockito 复制其行为。 (当然,Mockito 是在您模拟的被测系统的依赖项中提供 Future 的一种不错的方式。)
    猜你喜欢
    • 2016-04-18
    • 2013-10-27
    • 2012-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-14
    相关资源
    最近更新 更多