2017-08-13 147 views
1

我有一个类HttpClient有一个返回CompletableFuture功能:模拟CompletionException在测试

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代码?

回答

3

我得到这个由测试做这个工作:如果

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

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

不知道这是虽然最佳途径。

+2

我认为这是最好的方法:CompletableFuture是一个广泛使用和经过充分测试的库,因此您可以依靠它来测试代码,而不是尝试使用Mockito复制其行为。 (当然,Mockito是一个体面的方式来提供未来的系统测试中的依赖,您嘲笑。) –

+1

谢谢@JeffBowman! –