Spring Integration模拟出站网关失败

问题描述

我正在尝试在这样的单元测试中模拟出站网关的故障:

MessageHandler mockCognitiveAnalyze =
        mockMessageHandler().handleNextAndReply(m -> ResponseEntity.status(HttpStatus.UNAUTHORIZED).build());
this.mockIntegrationContext.substituteMessageHandlerFor("cognitiveServicesReadEndpoint",mockCognitiveAnalyze);

我期望的是,当调用 cognitiveServicesReadEndpoint 时,它将不会成功,并且流程应已完成(或者,在我的情况下,将应用重试建议,因此应重复执行) 。但是发生的是,不会引发任何异常或错误,并且将调用一个句柄。流程如下所示:

.handle(Http.outboundGateway(cognitiveServicesUri + "/vision/v3.0/read/analyze")
                .mappedRequestHeaders("Ocp-Apim-Subscription-Key")
                .mappedResponseHeaders("Operation-Location"),c -> c.advice(this.advices.retryAdvice())
                .id("cognitiveServicesReadEndpoint"))
.transform(p -> "")
.handle(Http.outboundGateway(h -> h.getHeaders().get("Operation-Location"))
        .mappedRequestHeaders("Ocp-Apim-Subscription-Key")
        .httpMethod(HttpMethod.GET)
        .expectedResponseType(String.class),this.advices.ocrSpec())

任何想法如何设置模拟处理程序以正确引发异常?

旁注: .transform(p->“”)是正确处理标头所必需的,请参见Spring Integration HTTP Outbound Gateway header not forwarder on a consecutive request

UPDATE1

此刻处理程序的外观如下:

.handle(Http.outboundGateway(h -> String.format("%s%s",uri,h.getHeaders()
        .get(CustomHeaders.DOCUMENT_ID.name())))
        .httpMethod(HttpMethod.GET)
        .expectedResponseType(byte[].class),c -> c.advice(this.advices.retryAdvice())
        .id("endpoint1"))
.wireTap(sf -> sf.enrichHeaders(h -> h.header("ocp-apim-subscription-key",computerVisionApiKey))
        .handle(Http.outboundGateway(cognitiveServicesUri + "/vision/v3.0/read/analyze")
                        .mappedRequestHeaders("Ocp-Apim-Subscription-Key")
                        .mappedResponseHeaders("Operation-Location"),c -> c.advice(this.advices.retryAdvice())
                        .id("cognitiveServicesReadEndpoint"))

以及测试代码

MessageHandler mockCognitiveAnalyze = mockMessageHandler().handleNext(m -> {
    throw new HttpClientErrorException(HttpStatus.UNAUTHORIZED);
});
this.mockIntegrationContext.substituteMessageHandlerFor("cognitiveServicesReadEndpoint",mockCognitiveAnalyze);

解决方法

MockMessageHandler.handleNextAndReply()提供了一个Function,它在handleMessageInternal()中被调用。由于没有与Resttemplate进行交互(您完全替代了它),因此您的HttpStatus.UNAUTHORIZED不会转换为异常。

您可能应该在RestTemplate上模拟handleNextAndReply()逻辑,并抛出相应的异常。

RestTemplate具有如下逻辑:

protected void handleResponse(URI url,HttpMethod method,ClientHttpResponse response) throws IOException {
    ResponseErrorHandler errorHandler = getErrorHandler();
    boolean hasError = errorHandler.hasError(response);
    if (logger.isDebugEnabled()) {
        try {
            int code = response.getRawStatusCode();
            HttpStatus status = HttpStatus.resolve(code);
            logger.debug("Response " + (status != null ? status : code));
        }
        catch (IOException ex) {
            // ignore
        }
    }
    if (hasError) {
        errorHandler.handleError(url,method,response);
    }
}

因此,您需要向errorHandler的{​​{1}}借阅和提出想法,并可能从提供的DefaultResponseErrorHandler中抛出相应的异常。或者,您可以直接扔一个ClientHttpResponse

更新

类似这样的东西:

HttpClientErrorException.Unauthorized
,

这是最终解决方案:

MessageHandler mockCognitiveAnalyze = mockMessageHandler().handleNextAndReply(m -> {
    throw new HttpClientErrorException(HttpStatus.UNAUTHORIZED);
});

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...