问题描述
我正在使用 Camel 进行单元测试,当我从 Camel In Action 存储库执行 this test 时,它运行良好,但是当我将路由类型从 SEDA 更改为 direct-vm它失败并显示以下消息:
引起:org.apache.camel.component.directvm.DirectVmConsumerNotAvailableException:端点上没有可用的消费者:direct-vm://camel。交换[ID....
SEDA 和 direct-vm 这两种类型的区别在于,第一种是异步的,第二种是同步的。这就是测试失败的原因吗?如何使测试适用于 direct-vm 类型的路由?
我使用的是 JDK 1.8 和 Camel 2.25.2
更新:我发现 adviceWith 中的 mockEndpoints() 方法存在问题,路由没有被模拟。这是我启动测试时打印在日志中的内容:
2021-07-20 16:27:36.501 INFO 31220 --- [ main] org.apache.camel.model.RouteDeFinition : Adviced route before/after as XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<route xmlns="http://camel.apache.org/schema/spring" customId="true" id="basicRoute">
<from uri="direct-vm:quotes"/>
<choice id="choice2">
<when id="when2">
<simple>${body} contains 'Camel'</simple>
<log id="log4" loggingLevel="INFO" message="camel route"/>
<to id="to11" uri="direct-vm:camel"/>
</when>
<otherwise id="otherwise2">
<log id="log5" loggingLevel="INFO" message="other route"/>
<to id="to12" uri="direct-vm:other"/>
</otherwise>
</choice>
</route>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<route xmlns="http://camel.apache.org/schema/spring" customId="true" id="basicRoute">
<from uri="direct-vm:hitme"/>
<choice id="choice2">
<when id="when2">
<simple>${body} contains 'Camel'</simple>
<log id="log4" loggingLevel="INFO" message="camel route"/>
<to id="to11" uri="direct-vm:camel"/>
</when>
<otherwise id="otherwise2">
<log id="log5" loggingLevel="INFO" message="other route"/>
<to id="to12" uri="direct-vm:other"/>
</otherwise>
</choice>
</route>
但是如果我使用 weaveByToUri 来模拟路由:
weaveByToUri("direct-vm:camel").replace().to("mock:direct-vm:camel");
weaveByToUri("direct-vm:other").replace().to("mock:direct-vm:other");
模拟路由并且测试有效:
2021-07-20 16:30:42.409 INFO 9920 --- [ main] org.apache.camel.model.RouteDeFinition : Adviced route before/after as XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<route xmlns="http://camel.apache.org/schema/spring" customId="true" id="basicRoute">
<from uri="direct-vm:quotes"/>
<choice id="choice2">
<when id="when2">
<simple>${body} contains 'Camel'</simple>
<log id="log4" loggingLevel="INFO" message="camel route"/>
<to id="to11" uri="direct-vm:camel"/>
</when>
<otherwise id="otherwise2">
<log id="log5" loggingLevel="INFO" message="other route"/>
<to id="to12" uri="direct-vm:other"/>
</otherwise>
</choice>
</route>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<route xmlns="http://camel.apache.org/schema/spring" customId="true" id="basicRoute">
<from uri="direct-vm:hitme"/>
<choice id="choice2">
<when id="when2">
<simple>${body} contains 'Camel'</simple>
<log id="log4" loggingLevel="INFO" message="camel route"/>
<pipeline>
<to uri="mock:direct-vm:camel"/>
</pipeline>
</when>
<otherwise id="otherwise2">
<log id="log5" loggingLevel="INFO" message="other route"/>
<pipeline>
<to uri="mock:direct-vm:other"/>
</pipeline>
</otherwise>
</choice>
</route>
解决方法
如果您想在测试中使用 direct-vm,您必须运行另一个 CamelContext,其中包含您要测试的 direct-vm 端点的使用者。您可以使用 Main 类来执行此操作。
public class Example extends CamelTestSupport {
@Override
protected CamelContext createCamelContext() throws Exception {
return new DefaultCamelContext();
}
@Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder(){
@Override
public void configure() throws Exception {
from("direct-vm:helloReceiver")
.routeId("helloReceiver")
.log("Message received: ${body}")
.to("mock:result");
}
};
}
@Test
public void testDirectVM() throws Exception{
RouteBuilder builder = new RouteBuilder(){
@Override
public void configure() throws Exception {
from("direct:helloSender")
.routeId("helloSender")
.to("direct-vm:helloReceiver");
}
};
MockEndpoint mockEndpoint = getMockEndpoint("mock:result");
mockEndpoint.expectedMessageCount(1);
mockEndpoint.message(0).body().isEqualTo("hello");
Main camelMain = new Main();
camelMain.addRouteBuilder(builder);
camelMain.start();
camelMain.getCamelTemplate()
.sendBody("direct:helloSender","hello");
mockEndpoint.assertIsSatisfied();
}
}
但是,最好将字符串变量与 setter 一起用于直接虚拟机端点,您可以在测试期间轻松更改为模拟端点。给它 id,你可以使用 weaveById 让它返回任何你需要的测试。
,错误消息 No consumers available on endpoint: ...
通常意味着您有生产者向同步端点发送消息,但没有消费者侦听此端点。
有没有可能你刚刚把制作人改成了direct-vm
?
顺便说一句:direct-vm
通常用于连接同一 JVM 内但来自不同 Camel 上下文的 Camel 路由。一个例子是在 OSGi 包之间。如果您只有 1 个 Camel 上下文,只需使用 direct
。