我正试图在这样的单元测试中模拟出站网关的失败:
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);
});