You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache Camel单元测试如何过滤路由仅启用指定路由

Apache Camel单元测试单方法级指定加载路由方案

问题背景

需要在Apache Camel单元测试中仅加载启用指定路由,例如仅加载ID为my-translation-route的路由,被测路由定义如下:

public class TestRoute extends RouteBuilder {
    @Override
    public void configure() {
        from("ftp://my-ftp-server:21/messages")
                .routeId("my-inbound-route")
                .to("direct:my-translation-route");

        from("direct:my-translation-route")
                .routeId("my-translation-route")
                .bean(MyBean.class)
                .to("direct:my-outbound-route");

        from ("direct:my-outbound-route")
                // 注意:原代码此处routeId与其他路由重复,会导致路由匹配异常
                .routeId("my-outbound-route")
                .to("http://my-http-server:8080/messages");
    }
}

此前尝试调用Model#filterRoutes、context.setRouteFilterPattern做路由过滤未生效,所有路由仍会全量加载,对应测试代码如下:

class TestRouteTest extends CamelTestSupport {
    @Override
    protected RoutesBuilder createRouteBuilder() {
        return new TestRoute();
    }

    @Override
    public boolean isUseAdviceWith() {
        return true;
    }

    @Test
    void testIfItWorks() throws Exception {
        context.setRouteFilterPattern("my-translation-route", null);

        AdviceWith.adviceWith(context, "my-translation-route", a -> {
            a.mockEndpointsAndSkip("direct:my-outbound-route");
        });

        context.start();

        getMockEndpoint("mock:direct:my-outbound-route").expectedBodyReceived().expression(constant("Hahaha! 42"));

        template.sendBodyAndHeaders("direct:my-translation-route", "42", null);

        assertMockEndpointsSatisfied();
    }
}

目前已知重写CamelTestSupport#getRouteFilterIncludePattern可实现路由过滤:

@Override
public String getRouteFilterIncludePattern() {
    return "my-translation-route";
}

但该配置会作用于测试类下所有测试方法,无法满足单测试方法粒度的路由加载控制需求。

失效原因

context.setRouteFilterPattern不生效的核心原因:路由过滤逻辑是在Camel上下文启动阶段、解析RouteBuilder路由定义时执行的,测试方法内调用set方法时,所有路由定义已经完成解析加载,再设置过滤规则不会生效。
重写getRouteFilterIncludePattern属于上下文初始化前加载的类级配置,因此默认对类下所有测试方法生效。

可落地方案

方案1:用AdviceWith在上下文启动前移除非目标路由

开启isUseAdviceWith()=true时,可在context.start()前通过AdviceWith直接删除/替换不需要的路由,不需要依赖全局过滤规则,配置仅对当前测试方法生效:

@Test
void testOnlyTranslationRoute() throws Exception {
    // 移除不需要的入站路由
    AdviceWith.adviceWith(context, "my-inbound-route", AdviceWithBuilder::remove);
    // 移除不需要的出站路由,也可以按测试需求替换from端点、mock端点
    AdviceWith.adviceWith(context, "my-outbound-route", AdviceWithBuilder::remove);

    // 织入目标路由的测试逻辑
    AdviceWith.adviceWith(context, "my-translation-route", a -> {
        a.mockEndpointsAndSkip("direct:my-outbound-route");
    });

    context.start();

    getMockEndpoint("mock:direct:my-outbound-route")
            .expectedBodyReceived().expression(constant("Hahaha! 42"));
    template.sendBody("direct:my-translation-route", "42");
    assertMockEndpointsSatisfied();
}

注意:删除路由前要确认目标路由和被删路由没有强依赖,否则上下文启动会抛出依赖缺失异常。

方案2:上下文启动前在测试方法内设置过滤规则

CamelTestSupport默认会为每个测试方法创建独立的Camel上下文(未手动开启上下文缓存的前提下),只要在context.start()调用前设置过滤规则,配置就只会作用于当前测试方法:

@Test
void testOnlyTranslationRoute() throws Exception {
    // 上下文启动前设置包含规则,仅匹配目标路由ID
    context.setRouteFilterPattern("my-translation-route", null);

    AdviceWith.adviceWith(context, "my-translation-route", a -> {
        a.mockEndpointsAndSkip("direct:my-outbound-route");
    });

    context.start();
    // 后续测试逻辑和原有逻辑一致
}

内容的提问来源于stack exchange,提问作者Bart Weber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 14:51:19