Reputation: 147
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
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
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