问题描述
我一直在将某些代码转换为异步代码.原始的单元测试使用了注释@Test(expected = MyExcpetion.class)
,但是我认为这不会起作用,因为我要声明的异常包装在java.util.concurrent.ExcutionException
中.我确实尝试过这样称呼我的未来,但是我的断言仍然失败,我不喜欢必须在return null
I have been converting some code to be asynchronous. The original unit test used the annotation @Test(expected = MyExcpetion.class)
but I don't think this will work because the exception I want to assert on is wrapped in java.util.concurrent.ExcutionException
. I did try calling my future like this but my assertion is still failing and I don't love that I had to add in return null
myApiCall.get(123).exceptionally((ex) -> {
assertEquals(ex.getCause(),MyCustomException.class)
return null
}
我也尝试过这种口味,但仍然无法使用
I also tried this flavor but still not working
myApiCall.get(123).exceptionally((ex) -> {
assertThat(ex.getCause())
.isInstanceOF(MyException.class)
.hasMessage("expected message etc")
return null;
}
如果找不到ID,我的API只会引发异常.我应该如何正确测试呢?无论如何,我可以使用该原始注释吗?
My API just throws exception if it can't find id. How should I be properly testing this? Can I use that original annotation in anyway?
运行时,我的api调用到达db.在此测试中,我将未来设置为返回错误,因此它实际上不会尝试与任何事物进行通信.被测试的代码看起来像这样
my api call reaches out to db when run. In this test I am setting up my future to return an error so it doesn't actually try to communicate with anything. the code under test looks like this
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
)
}
}
在单元测试中,我强制myService.getFromDB(id)
返回错误数据,以便我可以测试异常,还可以保持此单元测试不会与db等保持联系.
in the unit test I force myService.getFromDB(id)
to return bad data so I can test exception and also keep this a unit test don't reach out to db etc.
推荐答案
假设使用0
调用您的API会抛出异常:
Let's assume your API throws if called with 0
:
public static CompletableFuture<Integer> apiCall(int id) {
return CompletableFuture.supplyAsync(() -> {
if (id == 0) throw new RuntimeException("Please not 0!!");
else return id;
});
}
您可以使用以下代码测试它是否按预期工作(我正在使用TestNG,但我怀疑将其转换为JUnit测试不会太困难):
You can test that it works as expected with the following code (I'm using TestNG but I suspect it won't be too difficult to translate into a JUnit test):
@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();
}
请注意,第二个测试使用了这样的事实,即ExecutionException消息将包含原始异常类型和消息,并使用正则表达式捕获期望.如果使用JUnit无法做到这一点,则可以在try/catch块中调用result.get()
,在catch块中调用throw e.getCause();
.换句话说,是这样的:
Note that the second test uses the fact that the ExecutionException message will contain the original exception type and message and captures the expectation with a regex. If you can't do that with JUnit, you can call result.get()
in a try/catch block and call throw e.getCause();
in the catch block. In other words, something like this:
@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();
}
}
这篇关于如何在可完成的将来测试异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!