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