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())

知道我如何设置mock处理程序来正确地抛出异常吗?

附带说明:.transform(p->"(是正确处理标头所必需的,请参阅Spring Integration HTTP Outbound Gateway标头而非连续请求上的转发器

更新1

这就是处理程序目前的样子:

.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()提供一个在handleMessageInternal()中调用的Function。由于并没有和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的思想,它是一个DefaultResponseErrorHandler,可以从提供的ClientHttpResponse抛出相应的异常。或者你可以直接投一个HttpClientErrorException.Unauthorized

更新

类似这样的东西:

MockMessageHandler mockMessageHandler = mockMessageHandler();
mockMessageHandler.handleNext(message -> { 
throw new HttpClientErrorException.create(...);
});
this.mockIntegrationContext.substituteMessageHandlerFor("httpGateway", mockMessageHandler);

这是一个最终解决方案:

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

最新更新