问题描述
我正在尝试在这样的单元测试中模拟出站网关的故障:
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);
});