You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Dennis Bohnstedt Hansen <db...@miracle.dk> on 2016/10/13 12:22:06 UTC

CamelCdiRunner loads all routes in each test case (sometimes)

Hi

I'm having soms problems with camel-test-cdi in 2.17 (tested in 2.17.0,
2.17.1 and 2.17.2).

I have two projects containing similar routes and test cases, but the
behaviour is very different, and i'm unsure which is the intended
behaviour. In both projects, my RouteBuilders are annotated with the
following annotations, and are picked up by Wildfly with camel-wildfly
added.

@Startup
@ApplicationScoped
@ContextName("foo-context")

In my jUnit tests however, the routes of project 1 are only picked up, when
i add the RouteBuilder to @Beans(...) like this:

@RunWith(CamelCdiRunner.class)
@Beans(classes = {MyFooRouteBuilder.class})

... But in project 2, the routes are picked up (by Weld i guess) without
adding @Beans, and if i add @Beans i get the following error from Weld:

org.jboss.weld.exceptions.DeploymentException: Exception List with 1
exceptions:
Exception 0 :
org.apache.camel.FailedToStartRouteException: Failed to start route
MyFooRouteRoute because of duplicate id detected: MyFooRouteRoute. Please
correct ids to be unique among all your routes.
at
org.apache.camel.impl.DefaultCamelContext.startRoute(DefaultCamelContext.java:963)
at
org.apache.camel.impl.DefaultCamelContext.startRouteDefinitions(DefaultCamelContext.java:3295)
at
org.apache.camel.impl.DefaultCamelContext.doStartCamel(DefaultCamelContext.java:3018)

I've gone though the classpath, and it seems to be fairly similar with
regards to Camel, Weld and Injection, which leaves med with a couple of
questions:

1) Which is the intended behaviour? I've found an email from @astefanutti (
http://camel.465427.n5.nabble.com/Came-CDI-tests-start-non-test-routes-td5783324.html),
that says that all routes should be loaded by default in test cases, but
that does not seem desirable in larger projects.
2) If the default behaviur is "load all", how do i keep that from
happening, without changing my business-code?
3) If Weld and Camel versions are the same - where do i look for the
error??!?

Regards

/ Dennis Bohnstedt Hansen
  Software designer
  Miracle A/S - www.miracle.dk <http://www.miracleas.dk/>
  +45 53747254

Re: CamelCdiRunner loads all routes in each test case (sometimes)

Posted by Dennis Bohnstedt Hansen <db...@miracle.dk>.
Hi

Thanks for you quick answer!

>> 3) If Weld and Camel versions are the same - where do i look for the
error??!?
> Not sure I understand the question here :(

This refered to the fact, that i had two different behaviours in the two
projects - and i could'nt figure out which was the correct behaviour and
WHY they were different. You answer gave me a clue though. It turned out,
that one of my projects was a WAR project and the other was a JAR project,
and that beans.xml was not loaded on the WAR file (since it was located
/webapp/WEB-INF/beans.xml and therefor not picked up by the classloader).

This gave me a "solution" to my problem, even though it's not perfect.
Unfortunately you can't override src/main/resources/beans.xml with a
src/test/resources/beans.xml in Weld (
https://issues.jboss.org/browse/WELD-2054), but i was able to exclude the
package containing my RouteBuildes by adding an exclution to my beans.xml,
and having a "marker class" (ExcludeRouteBuildersFromTest.java) in
src/test/java.

<beans ...>
    <weld:scan>
        <!-- Exclude routes from beans scan...! -->
        <weld:exclude name="my.routebuilder.package.**" >
            <weld:if-class-available name="ExcludeRouteBuildersFromTest"/>
        </weld:exclude>
    </weld:scan>
</beans>

> That being said, we may want to improve CamelCdiRunner to meet your need,
provided that it does not hinder the original intent, that is simplicity
and convention over configuration.

I think that would be a very good idea. The problem with the current
default, is that if all routes a loaded, you have to handle all endpoints
in every class. "Unfortunately" you are helped by the fact that the
folowing code, actually mocks and skips ALL endpoints in the CamelContext,
not just endpoints in the current route being adviced, but i'm thinkin that
thats a bug that will be fixed at some point:

context.getRouteDefinition("MyRouteId").adviceWith(context, new
AdviceWithRouteBuilder() {
    public void configure() throws Exception {
        mockEndpointsAndSkip("*");
    }
});

But you would also have to replace "from endpoints" of all routes in every
test, if they communicate with resources that are not available in you unit
tests - and you can't advice with the same replaceFromWith(...), in
different classes, since advices with @Observable conflict when all routes
are loaded.

... But thanks again!

/Dennis

Re: CamelCdiRunner loads all routes in each test case (sometimes)

Posted by Antonin Stefanutti <an...@stefanutti.fr>.
Hi Dennis,

> On 13 Oct 2016, at 14:22, Dennis Bohnstedt Hansen <db...@miracle.dk> wrote:
> 
> Hi
> 
> I'm having soms problems with camel-test-cdi in 2.17 (tested in 2.17.0,
> 2.17.1 and 2.17.2).
> 
> I have two projects containing similar routes and test cases, but the
> behaviour is very different, and i'm unsure which is the intended
> behaviour. In both projects, my RouteBuilders are annotated with the
> following annotations, and are picked up by Wildfly with camel-wildfly
> added.
> 
> @Startup
> @ApplicationScoped
> @ContextName("foo-context")
> 
> In my jUnit tests however, the routes of project 1 are only picked up, when
> i add the RouteBuilder to @Beans(...) like this:
> 
> @RunWith(CamelCdiRunner.class)
> @Beans(classes = {MyFooRouteBuilder.class})
> 
> ... But in project 2, the routes are picked up (by Weld i guess) without
> adding @Beans, and if i add @Beans i get the following error from Weld:
> 
> org.jboss.weld.exceptions.DeploymentException: Exception List with 1
> exceptions:
> Exception 0 :
> org.apache.camel.FailedToStartRouteException: Failed to start route
> MyFooRouteRoute because of duplicate id detected: MyFooRouteRoute. Please
> correct ids to be unique among all your routes.
> at
> org.apache.camel.impl.DefaultCamelContext.startRoute(DefaultCamelContext.java:963)
> at
> org.apache.camel.impl.DefaultCamelContext.startRouteDefinitions(DefaultCamelContext.java:3295)
> at
> org.apache.camel.impl.DefaultCamelContext.doStartCamel(DefaultCamelContext.java:3018)
> 
> I've gone though the classpath, and it seems to be fairly similar with
> regards to Camel, Weld and Injection, which leaves med with a couple of
> questions:
> 
> 1) Which is the intended behaviour? I've found an email from @astefanutti (
> http://camel.465427.n5.nabble.com/Came-CDI-tests-start-non-test-routes-td5783324.html),
> that says that all routes should be loaded by default in test cases, but
> that does not seem desirable in larger projects.

For the time being, CamelCdiRunner bootstrap a Weld SE container with its discovery mode enabled, that is every explicit beans archive (that is with a beans.xml) that’s available in the classpath gets added to the deployment. @Beans annotations can then be used to add additional classes to that deployment, for example for test classes (generally test classes are not packaged in bean archives).

> 2) If the default behaviur is "load all", how do i keep that from
> happening, without changing my business-code?

The idea behind the CamelCdiRunner is to provide the simplest way to bootstrap your application in a SE CDI container for you to test. So it relies on what's available in the classpath. Besides, you can still rely on CDI features like alternatives and decorators, should you modify your application logic for testing purpose.

In case your classpath is too complex, the idea is to use Arquillian which leverages ShrinkWrap in order to build your test deployments as documented in [1].

That being said, we may want to improve CamelCdiRunner to meet your need, provided that it does not hinder the original intent, that is simplicity and convention over configuration.

> 3) If Weld and Camel versions are the same - where do i look for the
> error??!?

Not sure I understand the question here :(

Let us know if that helps.

[1]: http://camel.apache.org/cdi-testing.html#CDITesting-Arquillian

Antonin