当前位置: 首页 > 知识库问答 >
问题:

模仿IntegrationTests的CompletableFuture.join()

壤驷高洁
2023-03-14

我正在编写集成测试用例,我被困在无法模拟CompletableFuture.join()的地方

首先,我将进行异步调用并将所有响应添加到列表中

@Async("AsyncTaskExecutor")
    public <T> CompletableFuture<ResponseEntity<T>> callCarrierPost(
            ServiceConfig serviceConfig, Class<T> responseType, ExecutionContext executionContext,
            AdapterContext adapterContext) {
        ResponseEntity<T> responseEntity = carrierInvoker.postForObject(
                serviceConfig, responseType, executionContext, adapterContext);
        return CompletableFuture.completedFuture(responseEntity);
    }

一旦进行了异步调用,我将如下处理异步调用的响应,

private <T> List<ResponseEntity<T>> processResponseFutureList(List<CompletableFuture<ResponseEntity<T>>> responseEntityFutureList) {
        List<ResponseEntity<T>> responseEntityList = new ArrayList<>();
        responseEntityFutureList.forEach(responseEntityFuture -> {
            try {
                responseEntityList.add(responseEntityFuture.join());
            } catch (CompletionException ex) {
                if (ex.getCause() instanceof HttpStatusCodeException) {
                    HttpStatusCodeException httpStatusCodeException = ((HttpStatusCodeException) ex.getCause());
                    ResponseEntity<T> response = new ResponseEntity<>((T) httpStatusCodeException.getResponseBodyAsString(),
                            httpStatusCodeException.getResponseHeaders(),
                            httpStatusCodeException.getStatusCode());
                    responseEntityList.add(response);
                } else if (ex.getCause() instanceof ResourceAccessException &&
                        ex.getCause().getCause() instanceof SocketTimeoutException) {
                    responseEntityList.add(getErrorResponseEntity(HttpStatus.SERVICE_UNAVAILABLE,
                            TimeOutException.Code.PROVIDER_TIME_OUT.getVal(), ex.getMessage()));
                } else {
                    responseEntityList.add(getErrorResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR,
                            InternalServerException.Code.INTERNAL_M2_BROKER_ERROR.getVal(), ex.getMessage()));
                }
            }
        });
        return responseEntityList;
    }

在Process ResepseFutureList方法中,我试图模拟completableFuture.join()的响应以涵盖所有异常情况

所以我试着模仿completableFuture,但是运气不好,它没有抛出异常,而是给出了最初的响应。

@MockBean
    private CompletableFuture completableFuture;

Mockito.when(completableFuture.join())
                .thenReturn(new ResourceAccessException("I/O error on /uri", new SocketTimeoutException("Read Timeout")));

我实际上是测试新手,也从未有机会与“可完成的未来”合作。

有人可以帮助模拟可完成未来.join()抛出一个异常吗?

共有1个答案

许自强
2023-03-14

一般来说,不要模仿你不拥有的类型。特别是,CompletableFuture是一个巨大的应用编程接口,语义学非常复杂,我不建议嘲笑它。(你的团队可能会有不同的意见,但是CompletableFuture的大型和非封装的应用编程接口被认为是一个设计问题,尤其是在如何从外部控制CompletableFuture方面。)

此外,加入永远不会返回资源访问异常,也不会直接抛出一个。期货代表其他一些异步进程的结果,可能在另一个线程上;如果该进程引发资源访问异常,则与您发布的代码一样,联接将引发一个具有 getCause() 值的完成异常,该值是基础资源访问例外。

在Java9或更好的版本中,您可以使用ailedFuture作为静态工厂,传入原始ResourceAccessException,因为真正的CompletableFuture实现将为您包装它:

// You'll probably need to specify your generics here, but I can't see
// enough of your test to fill them in realistically.
CompletableFuture</* ... */> completableFuture
    = CompletableFuture.failedFuture(new ResourceAccessException(
        "I/O error on /uri",
        new SocketTimeoutException("Read Timeout")));

在Java8中,在没有静态工厂的情况下,如SO问题“CompletableFuture已经异常完成”,只需创建一个真正的CompletableFuture并异常完成它(利用上述外部控制设计问题):

CompletableFuture</* ... */> completableFuture
    = new CompletableFuture</* ... */>();
completableFuture.completeExceptionally(
    new ResourceAccessException(/*...*/));
 类似资料:
  • 但是,我得到一个UnfinishedStubbingException: 谁能提供更多的指导?

  • 问题内容: 我使用的规则的组合来实现CSS3 的跨浏览器兼容的方式可能的规则:我使用,,,和。 任何版本的Internet Explorer 是否都具有类似的属性?是否有针对旧版IE的专有过滤器,类似于以下规则在IE 6-8中的不透明度如何起作用? 问题答案: 在旧版本的IE中没有任何过渡效果。 我所知道的唯一接近它的方法是使用JQuery 和方法,它们在IE的所有版本中都有效。 但是,我应该警告

  • 我试图从类模拟方法(该类属于包)。 方法声明如下所示: 到目前为止,我有了以下测试代码: 但是,当我运行测试时,它在行中崩溃,出现以下错误: 有人知道这里出了什么问题吗?

  • 我有一个变量在一个类在测试情况下,我需要嘲笑它。我尝试过这样 但事实的确如此 giving me无法将给定对象格式化为日期 在一台机器和另一台机器上 它给我的日期不能为空。 我是Junit新手,需要帮助解决这个问题

  • 无法找出正确的方法来使用匹配器来识别我要处理的exchange方法的重载。我正在打的电话:

  • 问题内容: 我正在使用JavaScript。我想存储具有以下属性的 唯一 ,无序字符串值的列表: 快速询问“列表中是否有A”的方法? 一种快速的方法(如果列表中存在A,则从列表中删除A) 一种快速的方法“将A添加到列表(如果尚不存在)”。 我真正想要的是一套。有什么建议以最佳方式模仿JavaScript中的集合吗? 这个问题建议使用Object,其键存储属性,并且所有值都设置为true:这是明智的