如何在可完成的未来测试异常?

Bar*_*rry 5 java junit junit4 java-8 completable-future

我一直在将一些代码转换为异步.原始单元测试使用了注释,@Test(expected = MyExcpetion.class)但我认为这不会起作用,因为我要断言的异常包含在内java.util.concurrent.ExcutionException.我确实尝试过这样称呼我的未来,但我的断言仍然失败,我不喜欢我必须加入return null

myApiCall.get(123).exceptionally((ex) -> {
 assertEquals(ex.getCause(),MyCustomException.class)
 return null
}
Run Code Online (Sandbox Code Playgroud)

我也试过这种味道,但仍然无法正常工作

myApiCall.get(123).exceptionally((ex) -> {
 assertThat(ex.getCause())
  .isInstanceOF(MyException.class)
  .hasMessage("expected message etc")
 return null;
}
Run Code Online (Sandbox Code Playgroud)

如果我的API无法找到id,则会抛出异常.我应该如何正确测试?无论如何我可以使用原始注释吗?

我的api调用在运行时伸出到db.在这个测试中,我正在设置我的未来以返回错误,因此它实际上并没有尝试与任何东西进行通信.被测代码看起来像这样

 public class myApiCall  { 
   public completableFuture get(final String id){
   return myService.getFromDB(id)
    .thenApply( 
       //code here looks at result and if happy path then returns it after 
       //doing some transformation 
      //otherwise it throws exception 
   )
  }
 }
Run Code Online (Sandbox Code Playgroud)

在单元测试中我强制myService.getFromDB(id)返回坏数据,这样我就可以测试异常并保持这个单元测试不会到达db等.

ass*_*ias 6

假设在以下情况下调用您的API,我们假设0:

public static CompletableFuture<Integer> apiCall(int id) {
  return CompletableFuture.supplyAsync(() -> {
    if (id == 0) throw new RuntimeException("Please not 0!!");
    else return id;
  });
}
Run Code Online (Sandbox Code Playgroud)

您可以使用以下代码测试它是否按预期工作(我正在使用TestNG,但我怀疑转换为JUnit测试并不太难):

@Test public void test_ok() throws Exception {
  CompletableFuture<Integer> result = apiCall(1);
  assertEquals(result.get(), (Integer) 1);
}

@Test(expectedExceptions = ExecutionException.class,
      expectedExceptionsMessageRegExp = ".*RuntimeException.*Please not 0!!")
public void test_ex() throws Throwable {
  CompletableFuture<Integer> result = apiCall(0);
  result.get();
}
Run Code Online (Sandbox Code Playgroud)

请注意,第二个测试使用ExecutionException消息将包含原始异常类型和消息的事实,并使用正则表达式捕获期望.如果你不能用JUnit做到这一点,你可以调用result.get()try/catch块并调用throw e.getCause();catch块.换句话说,这样的事情:

@Test(expectedExceptions = RuntimeException.class,
      expectedExceptionsMessageRegExp = "Please not 0!!")
public void test_ex() throws Throwable {
  CompletableFuture<Integer> result = apiCall(0);
  try {
    result.get();
  } catch (ExecutionException e) {
    throw e.getCause();
  }
}
Run Code Online (Sandbox Code Playgroud)