0

我正在使用 Camel 进行单元测试,当我从 Camel In Action 存储库执行此测试时,它运行良好,但是当我将路由类型从 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>

应该是mockEndpoints方法中的错误吗?

4

2 回答 2

1

如果您想在测试中使用 direct-vm,则必须运行另一个包含您要测试的 direct-vm 端点的使用者的 CamelContext。您可以使用 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 让它返回你需要的测试。

于 2021-07-19T17:45:32.483 回答
0

错误消息No consumers available on endpoint: ...通常意味着您有一个将消息发送到同步端点的生产者,但没有侦听此端点的消费者。

有没有可能您只是将生产者更改为direct-vm

顺便说一句:direct-vm通常用于连接同一 JVM 内但来自不同 Camel 上下文的 Camel 路由。一个例子是在 OSGi 包之间。如果您只有 1 个 Camel 上下文,请使用direct.

于 2021-07-16T09:05:42.743 回答