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

编写Apache Camel路由测试用例时断言失败问题求助

Apache Camel测试断言失败与AdviceWith报错解决方案

问题概述

  1. 测试断言失败:期望mock://seda:processMessage?blockWhenFull=true收到1条消息,但实际为0,调试确认消息能正常流转
  2. 直接修改路由添加mock:前缀可让测试生效,但希望不改动路由实现
  3. 使用AdviceWith时触发错误:Cannot advice routes as there are no routes

原因分析

1. @MockEndpoints断言失败原因

路由中使用了parallelProcessing()和自定义线程池,消息在异步线程中处理,测试主线程在异步线程完成前就执行了mock.assertIsSatisfied(),导致断言时消息尚未到达mock端点。

2. AdviceWith报错原因

调用AdviceWith时传入的是目标端点地址(Endpoints.SEDA_PROCESS_ENDPOINT),但AdviceWith需要指定路由ID;同时没有在Camel上下文启动前执行AdviceWith,路由初始化完成后无法修改。

解决方案

方案一:修复@MockEndpoints的异步处理问题

无需修改路由,仅调整测试逻辑,给异步线程足够的处理时间:

@Test
void test() throws Exception {
    mock.expectedBodiesReceived(costIQPayloadString());
    // 设置超时时间(如10秒),确保异步线程完成消息处理
    mock.setResultWaitTime(10000);

    // 改用任意参数匹配,避免对象equals不匹配导致mock失效
    Mockito.when(rulesEngineClientMock.validateRules(Mockito.any(CostIQRetail.class)))
           .thenReturn(costIQObject());

    Map<String, Object> headers = new HashMap<>();
    headers.put("appName", "costIQ");

    template.sendBodyAndHeaders(Endpoints.SEDA_SEND_ENDPOINT, costIQObject(), headers);

    mock.assertIsSatisfied();
}

方案二:正确使用AdviceWith修改路由

在Camel上下文启动前执行AdviceWith,且指定路由ID而非端点地址:

@SpringBootTest
@CamelSpringBootTest
public class CamelRouteTests3 {

    @Autowired
    private ProducerTemplate template;

    @Autowired
    private CamelContext context;

    private MockEndpoint mock;

    @Mock
    private RulesEngineClient rulesEngineClientMock;

    // 在测试初始化阶段执行AdviceWith,确保路由启动前完成修改
    @BeforeEach
    void setup() throws Exception {
        // 针对路由ID为Endpoints.SEDA_SEND_ENDPOINT的路由进行修改
        AdviceWith.adviceWith(context, Endpoints.SEDA_SEND_ENDPOINT, a -> {
            // 自动将所有发送到Endpoints.SEDA_PROCESS_ENDPOINT的请求转发到mock端点
            a.mockEndpoints(Endpoints.SEDA_PROCESS_ENDPOINT);
        });
        // 获取自动生成的mock端点
        mock = context.getEndpoint("mock:" + Endpoints.SEDA_PROCESS_ENDPOINT, MockEndpoint.class);
    }

    // 测试方法逻辑同方案一...
    @Test
    void test() throws Exception {
        mock.expectedBodiesReceived(costIQPayloadString());
        mock.setResultWaitTime(10000);

        Mockito.when(rulesEngineClientMock.validateRules(Mockito.any(CostIQRetail.class)))
               .thenReturn(costIQObject());

        Map<String, Object> headers = new HashMap<>();
        headers.put("appName", "costIQ");

        template.sendBodyAndHeaders(Endpoints.SEDA_SEND_ENDPOINT, costIQObject(), headers);

        mock.assertIsSatisfied();
    }
}

额外优化建议

  • 测试时可通过AdviceWith关闭并行处理,彻底避免异步问题:
    a.replaceFromWith(Endpoints.SEDA_SEND_ENDPOINT).removeMulticastParallelProcessing();
    
  • 确保CostIQRetail类的equals方法实现正确,避免参数匹配和断言失败

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 18:15:36