Joselo
Joselo

Reputation: 147

No camel consumer available for routes of type direct-vm when testing

I'm working with unit tests using Camel and, When I execute this test from Camel In Action repository it works perfectly but when I change the route type from SEDA to direct-vm it fails with the following message:

Caused by: org.apache.camel.component.directvm.DirectVmConsumerNotAvailableException: No consumers available on endpoint: direct-vm://camel. Exchange[ID....

The difference of these 2 types, SEDA and direct-vm, is that the first is asynchronous and the second is synchronous. Is that the reason why the test fails? How can I make the test work for direct-vm type of routes?

I'm using JDK 1.8 and Camel 2.25.2

UPDATE: I have found an issue with the mockEndpoints() method inside the adviceWith, the routes are not being mocked. This is what is printed in the logs when I launch the test:

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>

But if I use instead weaveByToUri to mock the routes:

weaveByToUri("direct-vm:camel").replace().to("mock:direct-vm:camel");
weaveByToUri("direct-vm:other").replace().to("mock:direct-vm:other");

The routes are mocked and the test works:

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>

Should It be a bug in the mockEndpoints method?

Upvotes: 0

Views: 1519

Answers (2)

Pasi &#214;sterman
Pasi &#214;sterman

Reputation: 2187

If you want to use direct-vm in a test you'll have to run another CamelContext that contains consumer for the direct-vm endpoint you want to test. You can do this with Main class.

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();
    }
}

However it would be better to just to use string variable with setter for the direct-vm endpoint that you can easily change to mock endpoint during testing. Give it id and you can use weaveById to make it return whatever you need for the tests.

Upvotes: 1

burki
burki

Reputation: 7005

The error message No consumers available on endpoint: ... typically means you have a producer that sends messages to a synchronous endpoint but no consumer that listens to this endpoint.

Is it possible that you just changed the producer to direct-vm?

By the way: direct-vm is typically used to connect Camel routes inside the same JVM but from different Camel contexts. One example for this is between OSGi bundles. If you only have 1 Camel context, just use direct.

Upvotes: 0

Related Questions