apache / camel-quarkus

Apache Camel Quarkus
https://camel.apache.org
Apache License 2.0
256 stars 191 forks source link

Error No consumers available on endpoint in Unit test with yaml routes #4927

Open acasanova99 opened 1 year ago

acasanova99 commented 1 year ago

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

acasanova99 commented 1 year ago

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>
jamesnetherton commented 1 year ago

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.

acasanova99 commented 1 year ago

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.

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

jamesnetherton commented 1 year ago

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;
}
acasanova99 commented 1 year ago

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.

MikaelAnderssonWigander commented 11 months ago

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!");
    }
}