9 Replies Latest reply on Jul 13, 2012 7:02 AM by edevera

    CamelTestSupport problem

    edevera

      I am trying to test my camel route builder (which contains endpoints with switchyard as a component) based on the CamelTestSupport class that looks like this:

       

       

      import org.edevera.model.Entity;
      import org.apache.camel.*;
      import org.apache.camel.builder.RouteBuilder;
      import org.apache.camel.component.properties.PropertiesComponent;
      import org.apache.camel.model.ProcessorDefinition;
      import org.apache.camel.test.junit4.CamelTestSupport;
      import org.junit.Test;
      
      
      /**
      * @author: Eduardo de Vera
      * Date: 6/29/12
      * Time: 12:41 AM
      */
      public class MyRouterBuilderTest extends CamelTestSupport {
      
      
          @EndpointInject(uri=MyRouteBuilder.ENDPOINT_MY_SERVICE)
          private ProducerTemplate producerTemplate;
      
      
          protected RouteBuilder createRouteBuilder() throws Exception {
              return new MyRouteBuilder();
          }
      
      
          @Test
          public void testSendEntityAndSave() throws InterruptedException {
              Entity body = new Entity();
              producerTemplate.sendBodyAndHeader(body, "operation", "save");
              Thread.sleep(1000);
              assertTrue(true);
          }
      
      
          protected CamelContext createCamelContext() throws Exception {
              CamelContext context = super.createCamelContext();
              //Preparing properties
              PropertiesComponent prop = context.getComponent("properties", PropertiesComponent.class);
              prop.setLocation("classpath:router.properties");
      
      
              //  Substituting switchyard component for a seda.
              return context;
          }
      
      
      
      
          @Override
          protected void debugBefore(Exchange exchange, Processor processor, ProcessorDefinition definition, String id, String label) {
              System.out.println("Id:" + id + ", Label:" + label);
          }
      }
      {code}
      
      and I run into the following problem:
      
      {code}
      org.apache.camel.CamelExecutionException: Exception occurred during execution on the exchange: Exchange[Message: 0-null|]
                at org.apache.camel.util.ObjectHelper.wrapCamelExecutionException(ObjectHelper.java:1237)
                at org.apache.camel.util.ExchangeHelper.extractResultBody(ExchangeHelper.java:509)
                at org.apache.camel.impl.DefaultProducerTemplate.extractResultBody(DefaultProducerTemplate.java:442)
                at org.apache.camel.impl.DefaultProducerTemplate.extractResultBody(DefaultProducerTemplate.java:438)
                at org.apache.camel.impl.DefaultProducerTemplate.sendBodyAndHeader(DefaultProducerTemplate.java:152)
                at org.apache.camel.impl.DefaultProducerTemplate.sendBodyAndHeader(DefaultProducerTemplate.java:354)
                at com.edevera.services.MyRouterBuilderTest.testSendEntityAndSave(MyRouterBuilderTest.java:28)
                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
                at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
                at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
                at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
                at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
                at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
                at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:47)
                at org.junit.rules.RunRules.evaluate(RunRules.java:18)
                at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
                at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
                at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
                at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
                at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
                at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
                at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
                at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
                at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
                at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
                at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
                at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:76)
                at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195)
                at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
      Caused by: java.lang.NullPointerException
                at org.switchyard.component.camel.SwitchYardProducer.lookupServiceReference(SwitchYardProducer.java:94)
                at org.switchyard.component.camel.SwitchYardProducer.process(SwitchYardProducer.java:80)
                at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
                at org.apache.camel.processor.UnitOfWorkProcessor.processAsync(UnitOfWorkProcessor.java:150)
                at org.apache.camel.processor.UnitOfWorkProcessor.process(UnitOfWorkProcessor.java:117)
                at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:99)
                at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:86)
                at org.apache.camel.processor.UnitOfWorkProducer.process(UnitOfWorkProducer.java:63)
                at org.apache.camel.impl.ProducerCache$2.doInProducer(ProducerCache.java:352)
                at org.apache.camel.impl.ProducerCache$2.doInProducer(ProducerCache.java:324)
                at org.apache.camel.impl.ProducerCache.doInProducer(ProducerCache.java:223)
                at org.apache.camel.impl.ProducerCache.sendExchange(ProducerCache.java:324)
                at org.apache.camel.impl.ProducerCache.send(ProducerCache.java:169)
                at org.apache.camel.impl.DefaultProducerTemplate.send(DefaultProducerTemplate.java:111)
                at org.apache.camel.impl.DefaultProducerTemplate.sendBodyAndHeader(DefaultProducerTemplate.java:150)
                ... 33 more
      
      

       

      Can anyone help me out on this one? I tried using SwitchyardRunner based tests but I can't manage to obtain a reference to the different components that interact during an exchange (as explained here: https://community.jboss.org/thread/202157?tstart=0), so I am trying to at least test the Camel Route Builder.

        • 1. Re: CamelTestSupport problem
          kcbabo

          SwitchYardRunner will bootstrap the SY runtime and deploy your application as part of the unit test initialization.  CamelTestSupport won't do any of that, which leads to the NPE you pasted above.  I replied on your other thread and hopefully one of the alternatives I listed will work out.  If not, we can talk about how to improve our current test support to handle your requirements.

          • 2. Re: CamelTestSupport problem
            edevera

            I understand your point but I think that having to start switchyard runtime in order to be able to test a Camel Route Builder can become an overkill. The reason why I say this is because SwitchYardRunner (as well as the rest of the Arquillian based testing) is a framework for Integration Testing which imposes replicating as much as possible the container and the resources in it (in my case I have to set up resources related to transactions). From my point of view, it would be easier to be able to use the CamelTestSupport and have the switchyard endpoint mocked so that I can verify that tests flow according to the routing.

             

            At the moment when I try to mock the switchyard components by using CamelTestSupport together with the @Produce and @EndpointInject annotations, I get the following error:

             

            java.lang.IllegalArgumentException: Invalid type: org.apache.camel.component.mock.MockEndpoint which cannot be injected via @EndpointInject/@Produce for: Endpoint[switchyard://MyService
            
            • 3. Re: CamelTestSupport problem
              splatch

              Could you try to add following method in your test:

                  @Override

                  public String isMockEndpoints() {

                      return "switchyard*";

                  }

               

              Then for every matching switchyard endpoint you will have a mock.

              • 4. Re: CamelTestSupport problem
                edevera

                I am afraid it hasnt worked as I get the same error.

                 

                Nevertheless I do the this new line in the logging:

                 

                17:41:26,968 INFO  [org.apache.camel.impl.InterceptSendToMockEndpointStrategy] Adviced endpoint [switchyard://myService] with mock endpoint [mock:switchyard:myService]

                 

                 

                But at the end the error message is the same:

                 

                 

                java.lang.IllegalArgumentException: Invalid type: org.apache.camel.component.mock.MockEndpoint which cannot be injected via @EndpointInject/@Produce for: Endpoint[switchyard://myService]
                          at org.apache.camel.impl.CamelPostProcessorHelper.getInjectionValue(CamelPostProcessorHelper.java:164)
                          at org.apache.camel.spring.CamelBeanPostProcessor.injectField(CamelBeanPostProcessor.java:208)
                          at org.apache.camel.spring.CamelBeanPostProcessor$1.doWith(CamelBeanPostProcessor.java:196)
                          at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:513)
                          at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:490)
                          at org.apache.camel.spring.CamelBeanPostProcessor.injectFields(CamelBeanPostProcessor.java:192)
                          at org.apache.camel.spring.CamelBeanPostProcessor.postProcessBeforeInitialization(CamelBeanPostProcessor.java:94)
                          at org.apache.camel.test.junit4.CamelTestSupport.postProcessTest(CamelTestSupport.java:307)
                          at org.apache.camel.test.junit4.CamelTestSupport.doSetUp(CamelTestSupport.java:219)
                          at org.apache.camel.test.junit4.CamelTestSupport.setUp(CamelTestSupport.java:167)
                          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                          at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
                          at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
                          at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
                          at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
                          at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
                          at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:47)
                          at org.junit.rules.RunRules.evaluate(RunRules.java:18)
                          at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
                          at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
                          at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
                          at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
                          at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
                          at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
                          at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
                          at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
                          at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
                          at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
                          at org.junit.runners.Suite.runChild(Suite.java:128)
                          at org.junit.runners.Suite.runChild(Suite.java:24)
                          at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
                          at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
                          at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
                          at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
                          at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
                          at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
                          at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
                          at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
                

                 

                Any ideas why this might be happening would be much appreciated! Thanks.

                • 5. Re: CamelTestSupport problem
                  splatch

                  Hey Eduardo,

                  It was my mistake, use isMockEndpointsAndSkip method. Then the destination endpoint will never be called. This example works as you wish:

                   

                  package org.switchyard.component.camel;
                  
                  
                  import org.apache.camel.builder.RouteBuilder;
                  import org.apache.camel.component.mock.MockEndpoint;
                  import org.apache.camel.test.junit4.CamelTestSupport;
                  import org.junit.Test;
                  import org.junit.runner.RunWith;
                  import org.junit.runners.BlockJUnit4ClassRunner;
                  
                  
                  @RunWith(BlockJUnit4ClassRunner.class)
                  public class CamelTest extends CamelTestSupport {
                  
                      @Test
                      public void testX() throws Exception {
                          MockEndpoint endpoint = getMockEndpoint("mock:switchyard:service");
                          endpoint.expectedBodiesReceived("asdf");
                  
                          template.sendBody("direct:foo", "asdf");
                  
                          endpoint.assertIsSatisfied();
                      }
                  
                  
                      @Override
                      public String isMockEndpointsAndSkip() {
                          return "switchyard*";
                      }
                  
                      @Override
                      protected RouteBuilder createRouteBuilder() throws Exception {
                          return new RouteBuilder() {
                              @Override
                              public void configure() throws Exception {
                                  from("direct:foo").to("switchyard://service");
                              }
                          };
                      }
                  }
                  
                  • 6. Re: CamelTestSupport problem
                    splatch

                    Ok, for Switchyard 0.5 (Camel 2.9.2) solution is:

                    package org.switchyard.component.camel;
                    
                    import org.apache.camel.builder.RouteBuilder;
                    import org.apache.camel.component.mock.MockEndpoint;
                    import org.apache.camel.test.junit4.CamelTestSupport;
                    import org.junit.Test;
                    import org.junit.runner.RunWith;
                    import org.junit.runners.BlockJUnit4ClassRunner;
                    
                    
                    @RunWith(BlockJUnit4ClassRunner.class)
                    public class CamelTest extends CamelTestSupport {
                    
                        @Test
                        public void testX() throws Exception {
                            MockEndpoint endpoint = getMockEndpoint("mock:switchyard:service");
                            endpoint.expectedBodiesReceived("asdf");
                    
                            template.sendBody("direct:foo", "asdf");
                    
                            endpoint.assertIsSatisfied();
                        }
                    
                    
                        @Override
                        protected RouteBuilder createRouteBuilder() throws Exception {
                            return new CdbRouteBuilder() {
                                @Override
                                public void configure() throws Exception {
                                    // testing overrides
                                    interceptSendToEndpoint("switchyard://service")
                                        .skipSendToOriginalEndpoint() // cut off external endpoint
                                        .to("mock:switchyard:service");
                                    super.configure();
                                }
                            };
                        }
                    }
                    
                    
                    /**
                     * Main route builder.
                     */
                    class CdbRouteBuilder extends RouteBuilder { 
                        @Override
                        public void configure() throws Exception {
                            from("direct:foo").to("switchyard://service");
                        }
                    }
                    
                    • 7. Re: CamelTestSupport problem
                      edevera

                      I have tried what you have suggested but I continue to run into a NullPointerException when SwitchyardProducer tries to lookupServiceReference.

                       

                      My route builder looks like this:

                       

                      @Route(SwitchyardCamelService.class)
                      public class SwitchyardRouteBuilder extends RouteBuilder {
                      
                      
                          protected static final String ENDPOINT_SERVICE_CAMEL = "{{SwitchyardCamelService}}";
                          protected static final String ENDPOINT_SERVICE_A = "{{SwitchyardServiceA}}";
                          protected static final String ENDPOINT_SERVICE_B = "{{SwitchyardServiceB}}";
                          protected static final String ENDPOINT_SERVICE_C = "{{SwitchyardServiceC}}";
                      
                      
                          @Override
                          public void configure() throws Exception {
                      
                      
                              final ModelCamelContext context = getContext();
                              PropertiesComponent propertiesComponent = context.getComponent("properties", PropertiesComponent.class);
                              propertiesComponent.setLocation("classpath:router.properties");
                      
                      
                              String camelService = context.resolvePropertyPlaceholders(ENDPOINT_SERVICE_CAMEL);
                              String serviceA= context.resolvePropertyPlaceholders(ENDPOINT_SERVICE_A);
                              String serviceB = context.resolvePropertyPlaceholders(ENDPOINT_SERVICE_B);
                              String serviceC = context.resolvePropertyPlaceholders(ENDPOINT_SERVICE_C);
                      
                      
                              from(centralToCMDBServiceEndpoint)
                                      .choice()
                                          .when(and(body().isInstanceOf(EntityA.class), header("operation").isEqualTo("save")))
                                              .log("EntityA operation")
                                              .to(serviceA + "?operationName=save")
                                              .to(serviceC)
                                          .when(and(body().isInstanceOf(EntityA.class), header("operation").isEqualTo("update")))
                                              .log("EntityA update operation")
                                              .to(serviceA + "?operationName=update")
                                              .to(serviceC)
                                          .when(and(body().isInstanceOf(EntityB.class), header("operation").isEqualTo("save")))
                                              .log("EntityB save operation")
                                              .to(serviceB + "?operationName=save")
                                              .to(serviceC)
                                          .when(and(body().isInstanceOf(EntityB.class), header("operation").isEqualTo("update")))
                                              .log("EntityB update operation")
                                              .to(serviceB + "?operationName=update")
                                              .to(serviceC)
                                          .otherwise()
                                              .choice()
                                                  .when(or(header("operation").isNotEqualTo("save"), header("operation").isNotEqualTo("update")))
                                                      .log("Unsupported operation")
                                                      .throwException(new OperationNotSupportedException())
                                                  .when(or(not(body().isInstanceOf(EntityA.class)), not(body().isInstanceOf(EntityB.class))))
                                                      .log("Unsupported entity")
                                                      .throwException(new EntityNotSupportedException())
                                                  .otherwise()
                                                      .log("Unexpected condition met")
                                              .end()
                                      .end();
                          }
                      }
                      
                      

                       

                      And my CamelTest like this:

                       

                       

                      /**
                       * @author: Eduardo de Vera
                       * Date: 6/29/12
                       * Time: 12:41 AM
                       */
                      public class SwitchyardRouterBuilderTest extends CamelTestSupport {
                      
                          protected static final String MOCK_ENDPOINT_SERVICE_A = "mock:switchyard:serviceA";
                          protected static final String MOCK_ENDPOINT_SERVICE_B = "mock:switchyard:serviceB";
                          protected static final String MOCK_ENDPOINT_SERVICE_C = "mock:switchyard:serviceC";
                      
                          @Produce(uri = CentralToCMDBRouteBuilder. ENDPOINT_SERVICE_CAMEL)
                          private ProducerTemplate producerTemplate;
                      
                          @EndpointInject(uri = MOCK_ENDPOINT_SERVICE_B)
                          private MockEndpoint mockServiceB;
                      
                          @EndpointInject(uri = MOCK_ENDPOINT_SERVICE_A)
                          private MockEndpoint mockServiceA;
                          @EndpointInject(uri = MOCK_ENDPOINT_SERVICE_C)
                          private MockEndpoint mockServiceC;
                      
                          @Override
                          protected RouteBuilder createRouteBuilder() throws Exception {
                              return new CentralToCMDBRouteBuilder() {
                                  @Override
                                  public void configure() throws Exception {
                                      interceptSendToEndpoint(CentralToCMDBRouteBuilder.ENDPOINT_SERVICE_A)
                                              .skipSendToOriginalEndpoint()
                                              .to(MOCK_ENDPOINT_SERVICE_A);
                                      interceptSendToEndpoint(CentralToCMDBRouteBuilder.ENDPOINT_SERVICE_B)
                                              .skipSendToOriginalEndpoint()
                                              .to(MOCK_ENDPOINT_SERVICE_B);
                                      interceptSendToEndpoint(CentralToCMDBRouteBuilder.ENDPOINT_SERVICE_C)
                                              .skipSendToOriginalEndpoint()
                                              .to(MOCK_ENDPOINT_SERVICE_C);
                                      super.configure();
                                  }
                              };
                          }
                      
                          @Test
                          public void testSendHostAndSave() throws Exception {
                              mockServiceA.expectedMessageCount(1);
                              mockServiceC.expectedMessageCount(1);
                      
                              EnityA body = new EntityA();
                              producerTemplate.sendBodyAndHeader(body, "operation", "save");
                      
                              mockServiceA.assertIsSatisfied();
                              mockServiceC.assertIsSatisfied();
                          }
                      
                          protected CamelContext createCamelContext() throws Exception {
                              CamelContext context = super.createCamelContext();
                              //Preparing properties
                              PropertiesComponent prop = context.getComponent("properties", PropertiesComponent.class);
                              prop.setLocation("classpath:router.properties");
                      
                              return context;
                          }
                      
                          @Override
                          public String isMockEndpoints() {
                              return "switchyard*";
                          }
                      
                          @Override
                          public boolean isUseDebugger() {
                              return true;
                          }
                      
                          @Override
                          protected void debugBefore(Exchange exchange, Processor processor, ProcessorDefinition definition, String id, String label) {
                              System.out.println("Id:" + id + ", Label:" + label);
                          }
                      
                      }
                      
                      
                      • 8. Re: CamelTestSupport problem
                        splatch

                        Hey,

                        I was able to get this test done with following steps:

                        • Remove isMockEndpoints - as you do this by hand using interceptSendToEndpoint
                        • I changed the constants in interceptSendToEndpoint to wildcards eg. switchyard://serviceA* - the star sign allows you to ignore operation name parameter
                        • In router.properties I used direct:foo as value for SwitchyardCamelService

                         

                        Best regards,

                        Lukasz

                        • 9. Re: CamelTestSupport problem
                          edevera

                          Worked like a charm! Thanks a lot for your help. I think it is a must to be able to test RouteBuilder independently from SwitchYard in order to have more fine grained control over the tests.