camel-quarkus
camel-quarkus copied to clipboard
Error No consumers available on endpoint in Unit test with yaml routes
Hello, I am having some problems when trying to test my camels routes in Quarkus v2.16.6.Final
.
If a try to test the following route (defined as a yaml file):
- route:
id: my-route-id
from:
uri: direct:my-uri-id
id: from-6ae3
steps:
- unmarshal:
id: unmarshal-b88a
json:
id: json-5d60
library: jackson
useDefaultObjectMapper: false
unmarshalType: my-custom-dto
- to:
uri: bean:my-java-bean
id: to-0e55
group: my-group
messageHistory: true
trace: true
logMask: true
startupOrder: 1
autoStartup: true
description: Bug time
And then I make a unit test like this:
@QuarkusTest
public class MyRouteRouteTest extends CamelQuarkusTestSupport {
private static final Logger LOG = Logger.getLogger(MyRouteRouteTest.class);
@Test
public void testRoute1() {
// Read a json file as an string to simulate a kafka message
final String sampleKafkaJsonStr = HelperFunctions
.getStreamContents(HelperFunctions.getResourceAsStream("kafka-messages/my-mock.json"));
// Apply the camel route to the previous input
TpaeJiraSR routeResult = (DtoReturnType) this.template.requestBody("direct:my-uri-id", sampleKafkaJsonStr);
// Perform the assertions
Assertions.assertEquals(routeResult.field1, "Whatever");
}
// Copy and paste the same test
@Test
public void testRoute1Copy() {
// Read a json file as an string to simulate a kafka message
final String sampleKafkaJsonStr = HelperFunctions
.getStreamContents(HelperFunctions.getResourceAsStream("kafka-messages/my-mock.json"));
// Apply the camel route to the previous input
TpaeJiraSR routeResult = (DtoReturnType) this.template.requestBody("direct:my-uri-id", sampleKafkaJsonStr);
// Perform the assertions
Assertions.assertEquals(routeResult.field1, "Whatever");
}
}
If a run the tests. The second one fails with the following error:
Caused by: org.apache.camel.component.direct.DirectConsumerNotAvailableException: No consumers available on endpoint: direct://my-uri-id. Exchange[]
.
So, when I use the same route in different tests, only the first test is executed without this error. I think that this is somehow related with the camel context since the test do recognize the test for the first time.
I have already try to clean the context with @TestProfile
as is mentioned here and also by injecting the camel context directly into the text.
I get to make my test work by translating the routes form yaml to java:
public class MyRoute extends RouteBuilder {
@Override
public void configure() throws Exception {
from("direct:my-route-uri-2")
.group("my-group")
.messageHistory()
.tracing()
.logMask()
.startupOrder(1)
.autoStartup(true)
.routeDescription("Bug Time")
.routeId("my-route-id")
.unmarshal().json(JsonLibrary.Jackson, MyDto.class)
.to("bean:MyClassBean")
.to("log:result");
}
}
And then, in the test, I needed to override the Route builder in order to include the route:
@QuarkusTest
public class MyRouteRouteTest extends CamelQuarkusTestSupport {
private static final Logger LOG = Logger.getLogger(MyRouteRouteTest.class);
@Override
protected RoutesBuilder createRouteBuilder() {
return new MyRoute();
}
And then everything works fine.
It can be something related to the CamelQuarkusTestSupport
? . Let my know if you need all my dependencies
I found this interesting message in the class CamelQuarkusTestSupport
.
@Override
protected final void doQuarkusCheck() {
//can run on Quarkus
//log warning in case that at least one RouteBuilder in the registry, it might mean, that unintentionally
// RouteBuilders are shared across or that RouteBuilder is created with @Produces
if (isUseRouteBuilder() && !context.getRegistry().findByType(RouteBuilder.class).isEmpty()) {
LOG.warn(
"Test with `true` in `isUserRouteBuilder' and `RouteBuilder` detected in the context registry. " +
"All tests will share this routeBuilder from the registry. This is usually not intended. " +
"If `@Produces` is used to create such a RouteBuilder, please refactor the code " +
"by overriding the method `createRouteBuilder()` instead.");
}
}
But I did NOT use any @Produces on my code. Then problem is that I cannot use yaml routes if I nned to override the previous method (RoutesBuilder
) in the test. It can be an error on the extension:
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-yaml-dsl</artifactId>
</dependency>
Maybe it's just a typo?
In the YAML example, you define direct:my-uir-id
. But in the test you are trying to produce to direct:my-uri-id
.
Maybe it's just a typo?
In the YAML example, you define
direct:my-uir-id
. But in the test you are trying to produce todirect:my-uri-id
.
Sorry, I have used complicated names in order to name my classes, so i just change all the names to "foo" names like my-uri in order to make this mr easier to understand. I mean. I made the typo when copying the code to github. My bad anyways
Are you able to use the latest Quarkus 3.x release? The problem seems fixed there.
If you can't switch to 3.x, and assuming you're exclusively coding your routes in YAML, the following workaround might work for you, if you add it into your test class.
@Override
public boolean isUseRouteBuilder() {
return false;
}
I am using v2.16.6.Final
. I will let you know if the error desapears in v.3.x when I move to that version.
Thanks you @jamesnetherton for the workaround in yaml.
I have a smilier issue but using Java DSL and Quarkus 3.5.3
@QuarkusTest
class CamelTest extends CamelQuarkusTestSupport {
@Override
public boolean isUseRouteBuilder() {
return false;
}
@Override
public boolean isUseAdviceWith() {
return true;
}
@Test
void myTest() throws Exception {
AdviceWith.adviceWith(context, "myRouteId", route -> {
route.interceptSendToEndpoint("seda:end_process")
.skipSendToOriginalEndpoint()
.to("mock:transform");
});
startRouteDefinitions();
getMockEndpoint("mock:transform").expectedBodyReceived();
template.sendBody("direct:myRoute", "Hello, world!");
}
}