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
相关产品推荐
相关产品推荐

