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

Apache Camel JmsReplyTo路由流程单元测试问题咨询

Camel路由单元测试:断言Exchange与模拟JMSReplyTo场景

先看一下你的路由流程和当前的测试代码,针对你提出的两个问题,我给你整理了具体的解决方案:


问题1:如何在processResponse Bean执行完成后对Exchange进行断言?

要在processResponse Bean执行后验证Exchange的状态,最直接的方式是利用Camel Test套件提供的MockEndpoint来捕获处理后的消息,或者通过ExchangeCallback直接获取处理后的Exchange对象。

方案1:使用MockEndpoint捕获结果

通过AdviceWith修改Build XML Response路由,在流程末尾添加一个Mock端点来接收处理后的消息,然后对Mock端点的消息进行断言:

@Test
@DirtiesContext
public void RouteFlowTest() throws Exception{
    // 创建Mock端点用于捕获处理完成后的Exchange
    MockEndpoint mockResult = camelContext.getEndpoint("mock:result", MockEndpoint.class);
    
    // 修改processResponse路由,在流程最后添加转发到Mock端点
    camelContext.getRouteDefinition("Build XML Response").adviceWith(camelContext, new AdviceWithRouteBuilder() {
        @Override
        public void configure() throws Exception {
            weaveAddLast().to("mock:result");
        }
    });

    // 准备测试用的Headers和Body
    Map<String,Object> jmsHeaders = new HashMap<>();
    jmsHeaders.put("Auth","helloWorld");
    jmsHeaders.put("JMSReplyTo","sample");
    String jmsBody = "Help Me";
    
    // 发送请求到direct:start
    incomingJmsRequestMessage.sendBodyAndHeaders("direct:start", jmsBody, jmsHeaders);
    
    // 验证Mock端点收到预期数量的消息
    mockResult.expectedMessageCount(1);
    mockResult.assertIsSatisfied();
    
    // 获取处理后的Exchange,进行具体断言
    Exchange processedExchange = mockResult.getExchanges().get(0);
    // 断言Body内容(替换成你的预期值)
    assertEquals("Processed response mismatch", "YourExpectedProcessedBody", processedExchange.getIn().getBody(String.class));
    // 验证JMSReplyTo Header是否保留
    assertEquals("JMSReplyTo header missing or incorrect", "sample", processedExchange.getIn().getHeader("JMSReplyTo"));
}

方案2:使用ExchangeCallback直接获取结果

如果你不想修改路由结构,也可以通过ProducerTemplate.send方法传入ExchangeCallback,直接获取经过整个流程处理后的Exchange对象:

@Test
@DirtiesContext
public void RouteFlowTestWithCallback() throws Exception{
    Map<String,Object> jmsHeaders = new HashMap<>();
    jmsHeaders.put("Auth","helloWorld");
    jmsHeaders.put("JMSReplyTo","sample");
    String jmsBody = "Help Me";
    
    // 发送请求并通过回调获取处理后的Exchange
    Exchange processedExchange = incomingJmsRequestMessage.send("direct:start", exchange -> {
        exchange.getIn().setBody(jmsBody);
        exchange.getIn().setHeaders(jmsHeaders);
        return exchange;
    });
    
    // 对处理后的Exchange进行断言
    assertEquals("Processed body not as expected", "YourExpectedProcessedBody", processedExchange.getIn().getBody(String.class));
    assertNotNull("JMSReplyTo header should exist", processedExchange.getIn().getHeader("JMSReplyTo"));
}

问题2:无需运行EMS服务器,从第一个路由开始测试并满足JMSReplyTo要求的方法

当然可以实现!你可以通过两种方式模拟JMS环境:使用Mock组件替换真实JMS端点,或者启动嵌入式JMS Broker,两种方式都不需要外部EMS服务器。

方案1:用Mock组件模拟JMS输入和JMSReplyTo

通过AdviceWith替换第一个路由的JMS输入端点为direct,同时拦截发送到JMSReplyTo的消息,转发到Mock端点进行验证:

@Before
public void setupRouteMocks() throws Exception {
    // 修改第一个路由,把JMS输入替换为模拟的direct端点
    camelContext.getRouteDefinition("Receive JMS Message").adviceWith(camelContext, new AdviceWithRouteBuilder() {
        @Override
        public void configure() throws Exception {
            replaceFromWith("direct:mockJmsInput");
        }
    });
    
    // 拦截所有JMS发送请求(包括JMSReplyTo的地址),转发到Mock端点
    camelContext.getRouteDefinition("Build XML Response").adviceWith(camelContext, new AdviceWithRouteBuilder() {
        @Override
        public void configure() throws Exception {
            interceptSendToEndpoint("jms:*")
                .skipSendToOriginalEndpoint() // 跳过真实JMS发送
                .to("mock:jmsReplyDestination");
        }
    });
}

@Test
@DirtiesContext
public void FullRouteTestWithMockJms() throws Exception{
    MockEndpoint mockJmsReply = camelContext.getEndpoint("mock:jmsReplyDestination", MockEndpoint.class);
    
    // 设置预期断言:JMS回复消息应包含指定的JMSReplyTo Header
    mockJmsReply.expectedHeaderReceived("JMSReplyTo", "sample");
    mockJmsReply.expectedMessageCount(1);
    
    // 发送测试消息到模拟的JMS输入端点
    Map<String,Object> jmsHeaders = new HashMap<>();
    jmsHeaders.put("Auth","helloWorld");
    jmsHeaders.put("JMSReplyTo","sample");
    String jmsBody = "Help Me";
    template.sendBodyAndHeaders("direct:mockJmsInput", jmsBody, jmsHeaders);
    
    // 验证所有预期是否满足
    mockJmsReply.assertIsSatisfied();
    
    // 还可以进一步断言回复消息的内容
    Exchange replyExchange = mockJmsReply.getExchanges().get(0);
    assertEquals("Reply body mismatch", "YourExpectedReplyBody", replyExchange.getIn().getBody(String.class));
}

方案2:使用嵌入式JMS Broker(比如ActiveMQ)

如果你想更贴近真实环境,但又不想依赖外部服务器,可以启动嵌入式ActiveMQ Broker,这样可以直接使用真实的JMS端点进行测试:

import org.apache.activemq.broker.BrokerService;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.component.mock.MockEndpoint;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.test.annotation.DirtiesContext;

import javax.inject.Inject;
import java.util.HashMap;
import java.util.Map;

public class FullRouteEmbeddedJmsTest {

    @Inject
    private ProducerTemplate template;

    @EndpointInject(uri = "mock:jmsReplyQueue")
    private MockEndpoint mockJmsReply;

    @BeforeClass
    public static void startEmbeddedBroker() throws Exception {
        // 启动嵌入式ActiveMQ Broker,无需外部服务
        BrokerService broker = new BrokerService();
        broker.addConnector("tcp://localhost:61616");
        broker.setPersistent(false); // 不持久化消息,测试结束后自动清理
        broker.start();
    }

    @Test
    @DirtiesContext
    public void testFullRouteWithEmbeddedJms() throws Exception {
        // 配置Mock端点监听JMSReplyTo指定的队列
        mockJmsReply.expectedMessageCount(1);
        mockJmsReply.expectedHeaderReceived("Auth", "helloWorld");

        // 发送消息到真实的JMS输入队列(由嵌入式Broker提供)
        Map<String,Object> jmsHeaders = new HashMap<>();
        jmsHeaders.put("Auth","helloWorld");
        jmsHeaders.put("JMSReplyTo","jms:queue:sample"); // 对应你的JMSReplyTo地址
        String jmsBody = "Help Me";
        template.sendBodyAndHeaders("{{jms.input.queue}}", jmsBody, jmsHeaders);

        // 验证断言
        mockJmsReply.assertIsSatisfied();
    }
}

注意:这种方式需要在你的测试依赖中添加ActiveMQ的相关包(比如activemq-broker和activemq-camel)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:38:27