Camel 重试 - 使用 MockEndpoint 进行单元测试重新交付尝试计数

问题描述 投票:0回答:1

我正在尝试编写简单的单元测试,验证 Camel 路由是否配置正确以及是否真正进行了重新传递尝试。我有这个路线构建器实现:

class LocalEndpoint extends RouteBuilder {
    private final CamelContext camelContext;
    private final String targetEndpoint;

    public LocalEndpoint(CamelContext camelContext, String targetEndpoint) {
        super(camelContext);
        this.camelContext = camelContext;
        this.targetEndpoint = targetEndpoint;
    }

    @Override
    public void configure() {
        onException(TargetServerErrorException.class)
            .maximumRedeliveries(2)
            .redeliveryDelay(2500)
            .retryAttemptedLogLevel(LoggingLevel.WARN)
            .process(exchange -> {
                // bellow equals 2
                int redeliveryAttempts = exchange.getIn().getHeader(Exchange.REDELIVERY_COUNTER, Integer.class);
            })
            .stop();

        from("direct:local-endpoint")
            .marshal()
            .json()
            .to(targetEndpoint)
            .choice()
            .when(header(HTTP_RESPONSE_CODE).isEqualTo("500"))
                .throwException(new TargetServerErrorException())
            .endChoice()
            .end();
    }

    public void callTarget(String objectId) {
        camelContext.createProducerTemplate().sendBody("direct:local-endpoint", Map.of("objectId", objectId));
    }
}

我想出了以下测试:

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class LocalEndpointTest {
    private static final String MOCK_ENDPOINT = "mock:target-endpoint";

    CamelContext camelContext;
    MockEndpoint mockEndpoint;

    LocalEndpoint localEndpoint;

    @BeforeAll
    void beforeAll() throws Exception {
        camelContext = new DefaultCamelContext();
        localEndpoint = new LocalEndpoint(camelContext, MOCK_ENDPOINT);
        camelContext.addRoutes(localEndpoint);
        camelContext.start();

        mockEndpoint = camelContext.getEndpoint(MOCK_ENDPOINT, MockEndpoint.class);
    }

    @AfterAll
    void afterAll() {
        camelContext.stop();
    }

    @Test
    void testCallTarget_serverError() throws InterruptedException {
        // given
        mockEndpoint.returnReplyHeader(Exchange.HTTP_RESPONSE_CODE, new ConstantExpression("500"));
        mockEndpoint.expectedMessageCount(3); // gives: AssertionError: mock://target-endpoint Received message count. Expected: <3> but was: <1>
        mockEndpoint.expectedHeaderReceived(Exchange.REDELIVERY_COUNTER, 2); // gives: AssertionError: mock://target-endpoint No header with name CamelRedeliveryCounter found for message: 0

        // when
        Throwable thrown = catchThrowable(() -> localEndpoint.callTarget("object-id"));

        // then
        mockEndpoint.assertIsSatisfied();
        assertThat(thrown)
            .cause().isInstanceOf(TargetServerErrorException.class)
            .hasMessageContaining("received:", 500);
    }
}

我预计会在消息计数断言中看到值 3,但令我惊讶的是它是 1。

我认为这个问题和

mockEndpoint
交换中缺少Camel标头可能与路由定义中分离的
onException(Exception.class)
块和不同的上下文有关,但我不确定,因为我对Camel不够了解。

有没有办法在如此简单的测试中验证重新传递尝试? 或者至少有可能在

CamelRedeliveryCounter
内以某种方式获得 Camel 标头(如
mockEndpoint
)?

骆驼版本:4.3.0

编辑:

我找到了此信息:https://camel.apache.org/manual/faq/how-do-i-retry-processing-a-message-from-a-certain-point-back-or-an -整个路线.html

问题可能是由于:

默认情况下,Apache Camel 将从故障点开始执行任何重新交付(重试)尝试

我添加了

.errorHandler(noErrorHandler())
并重新定义了路线:

onException(TargetServerErrorException.class)
    .maximumRedeliveries(2)
    .redeliveryDelay(2500)
    .retryAttemptedLogLevel(LoggingLevel.WARN)
    .process(exchange -> {
        int redeliveryAttempts = exchange.getIn().getHeader(Exchange.REDELIVERY_COUNTER, Integer.class); // equals 2
    });

from("direct:local-endpoint")
    .marshal()
    .json()
    .to("direct:retryable")
    .end();

from("direct:retryable")
    .errorHandler(noErrorHandler())
    .to(targetEndpoint)
    .choice()
    .when(header(HTTP_RESPONSE_CODE).isEqualTo("500"))
        .throwException(new TargetServerErrorException())
    .endChoice()

但它仍然不起作用 - 我得到:

java.lang.AssertionError: mock://target-endpoint Received message count. Expected: <3> but was: <1>
java unit-testing junit apache-camel
1个回答
0
投票

事实证明,FAQ中已经提到的解决方案确实工作正常,并且正是我正在寻找的。我在测试中也有一些垃圾,清理它们后,添加

mockEndpoint.reset()
一切都开始成功通过。

© www.soinside.com 2019 - 2024. All rights reserved.