Spring integration 出站网关Spring集成模拟失败
我试图在单元测试中模拟出站网关的故障,如下所示:Spring integration 出站网关Spring集成模拟失败,spring-integration,spring-integration-dsl,Spring Integration,Spring Integration Dsl,我试图在单元测试中模拟出站网关的故障,如下所示: MessageHandler mockCognitiveAnalyze = mockMessageHandler().handleNextAndReply(m -> ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()); this.mockIntegrationContext.substituteMessageHandlerFor("cognitiveSer
MessageHandler mockCognitiveAnalyze =
mockMessageHandler().handleNextAndReply(m -> ResponseEntity.status(HttpStatus.UNAUTHORIZED).build());
this.mockIntegrationContext.substituteMessageHandlerFor("cognitiveServicesReadEndpoint", mockCognitiveAnalyze);
.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())
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);
}
}
MockMessageHandler mockMessageHandler = mockMessageHandler();
mockMessageHandler.handleNext(message -> {
throw new HttpClientErrorException.create(...);
});
this.mockIntegrationContext.substituteMessageHandlerFor("httpGateway", mockMessageHandler);
我期望的是,当调用CognitiveServicesReadedPoint时,它不会成功,流应该完成(或者在我的例子中,应用了重试建议,因此应该重复)。但实际情况是,不会抛出任何异常或错误,并且会调用下一个句柄。流程如下所示:
MessageHandler mockCognitiveAnalyze =
mockMessageHandler().handleNextAndReply(m -> ResponseEntity.status(HttpStatus.UNAUTHORIZED).build());
this.mockIntegrationContext.substituteMessageHandlerFor("cognitiveServicesReadEndpoint", mockCognitiveAnalyze);
.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())
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);
}
}
MockMessageHandler mockMessageHandler = mockMessageHandler();
mockMessageHandler.handleNext(message -> {
throw new HttpClientErrorException.create(...);
});
this.mockIntegrationContext.substituteMessageHandlerFor("httpGateway", mockMessageHandler);
知道如何设置模拟处理程序以正确抛出异常吗
旁注:。要正确处理标头,需要转换(p->“”),请参阅
更新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()
中调用。由于与restmplate
(您完全替换它)没有交互,因此您的HttpStatus.UNAUTHORIZED
不会转换为异常
在这个问题上,您可能应该模拟一个restemplate
逻辑,因为您的handleNextAndReply()
会抛出相应的异常
RestTemplate
具有如下逻辑:
MessageHandler mockCognitiveAnalyze =
mockMessageHandler().handleNextAndReply(m -> ResponseEntity.status(HttpStatus.UNAUTHORIZED).build());
this.mockIntegrationContext.substituteMessageHandlerFor("cognitiveServicesReadEndpoint", mockCognitiveAnalyze);
.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())
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);
}
}
MockMessageHandler mockMessageHandler = mockMessageHandler();
mockMessageHandler.handleNext(message -> {
throw new HttpClientErrorException.create(...);
});
this.mockIntegrationContext.substituteMessageHandlerFor("httpGateway", mockMessageHandler);
因此,您需要借用errorHandler
的思想,它是一个DefaultResponseErrorHandler
,可以从提供的ClientHttpResponse
中抛出相应的异常。或者你可以直接抛出一个HttpClientErrorException.Unauthorized
更新
大概是这样的:
MessageHandler mockCognitiveAnalyze =
mockMessageHandler().handleNextAndReply(m -> ResponseEntity.status(HttpStatus.UNAUTHORIZED).build());
this.mockIntegrationContext.substituteMessageHandlerFor("cognitiveServicesReadEndpoint", mockCognitiveAnalyze);
.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())
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);
}
}
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);
});
我最终使用了mockserver。。。我不知道如何准确地实施你的建议,我下面的答案仍然不完全有效。。。似乎mockserver必须以不同的方式注入到Spring集成中,因为它目前没有拦截API调用。。。请举例说明你的建议好吗?或者你知道为什么mockserver不能正常工作吗?那是什么
restTemplate
?您是否将其注入那些Http.outboundGateway()
?如果您不使用restmplate
,您希望模拟服务器如何拦截restmplate
操作?并且在我的回答中看到更新。我正在自动连接restmplate并将其提供给模拟服务器。我认为这样它可以做一些魔术和拦截它,因为出站网关也使用resttemplate