Thanks for your advice. Here's my attempt to modify my test to use 
CamelSpringJUnit4ClassRunner and annotations to mock my SQL endpoint.

@RunWith(CamelSpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CamelConfig.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
@MockEndpoints("sql:*")
public class FooRouteTests {

        @Autowired
        CamelContext camelContext;

        @Produce
        ProducerTemplate template;

        @EndpointInject(uri = "mock:sql:*")
        MockEndpoint mockSql;

        @Test
        public void testMockSQLEndpoint() throws Exception {
                template.sendBody("direct:foo", "bar");

                mockSql.expectedMessageCount(1);
                // todo: take input message and return mock results 
(ArrayList<HashMap>)
                MockEndpoint.assertIsSatisfied(camelContext);
        }
}

For some reason, this results in an error, even though my CamelConfig works for 
configuring other tests.

Could not autowire field: org.apache.camel.CamelContext 
com.company.app.foo.FooRouteTests.camelContext; nested exception is 
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying 
bean of type [org.apache.camel.CamelContext] found for dependency: expected at 
least 1 bean which qualifies as autowire candidate for this dependency.

@Configuration
@ImportResource("classpath:META-INF/cxf/cxf.xml")
@ComponentScan("com.company.app")
public class CamelConfig extends CamelConfiguration {

        @Override
        protected void setupCamelContext(CamelContext camelContext) throws 
Exception {
                PropertiesComponent pc = new PropertiesComponent();
                pc.setLocation("classpath:application.properties");
                camelContext.addComponent("properties", pc);
                super.setupCamelContext(camelContext);
        }
}


On Jun 11, 2014, at 5:08 PM, Minh Tran <darth.minhs...@gmail.com> wrote:

> If you're using Spring, I recommend not extending any of the Camel Test 
> classes and using the Camel Enhanced Spring Test as described here
> http://camel.apache.org/spring-testing.html
> 
> The docs take a bit of getting use to because it describes several different 
> ways of testing via Spring but you just have to skip to the Camel Enhanced 
> Spring Test bits. It also doesn't describe how to test using a JavaConfig 
> class very well IMO. It only describes how to do this by extending 
> AbstractJUnit4SpringContextTests which is a really old way of doing spring 
> unit tests. I had to do a lot of experimenting to get it to work without 
> extending this class.
> 
> Here's an example I had, the only difference is my JavaConfig is embedded 
> into my unit test class, but there's no reason you couldn't refer to an 
> existing class. If you want to mock and skip your sql or soap calls, then 
> instead of using @MockEndPoints, use @MockEndPointsAndSkip.  Look further 
> down to see some gotchas that I encountered in all of this.
> 
> 
> @RunWith(CamelSpringJUnit4ClassRunner.class)
> @ContextConfiguration(loader = CamelSpringDelegatingTestContextLoader.class, 
> classes = RegexTest.JavaConfig.class)
> @MockEndpoints
> @DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
> public class RegexTest {
> 
>       @Produce(uri = "direct:start")
>       private ProducerTemplate producerTemplate;
> 
>       @EndpointInject(uri = "mock:direct:match")
>       private MockEndpoint matchEndpoint;
> 
>       @EndpointInject(uri = "mock:direct:nomatch")
>       private MockEndpoint noMatchEndpoint;
> 
>       @Configuration
>       public static class JavaConfig extends SingleRouteCamelConfiguration {
> 
>               @Override
>               public RouteBuilder route() {
>                       return new RouteBuilder() {
> 
>                               @Override
>                               public void configure() throws Exception {
>                                       
> from("direct:start").to("log:blah?showProperties=true").log("${property.scaleResponse.message}").choice().when()
>                                                       
> .simple("resource:classpath:simple/item_not_exists.txt").to("direct:match").otherwise().to("direct:nomatch").end();
>                                       from("direct:match").log("matched");
>                                       from("direct:nomatch").log("no match");
>                                       this.getContext().setTracing(true);
>                               }
>                       };
>               }
>       }
> 
>       @After
>       public void afterTest() throws InterruptedException {
>               matchEndpoint.assertIsSatisfied();
>               noMatchEndpoint.assertIsSatisfied();
>       }
> 
>       @Test
>       public void testMatch() {
>               InterfaceResponse response = new InterfaceResponse();
>               response.setMessage("ITEM XML Download  ended. : Item \"blah\" 
> does not exist. - ");
>               matchEndpoint.expectedMessageCount(1);
> 
>               producerTemplate.sendBodyAndProperty(null, "scaleResponse", 
> response);
> 
>       }
> 
> }
> 
> 
> The regex you provide to mockendpointandskip  and mock endpoint is important 
> to get right. I didn't add any regex to my example above because mocking all 
> endpoints (the default) was ok in my example. if you get this regex wrong, 
> camel doesn't warn you. You can turn on camel logging to see whether it has 
> mocked your endpoint correctly or not. It should say something like the 
> following. That's how you know it is working. 
> 
> INFO  org.apache.camel.impl.InterceptSendToMockEndpointStrategy - Adviced 
> endpoint [direct://start] with mock endpoint [mock:direct:start]
> 
> The regex value matching is a bit strange, if it doesn't match your endpoint 
> even though you are absolutely sure it is correct, try tacking on ".*" on the 
> end of it, this fixed it up for me many times. IMO I think it's a bug in the 
> camel regex matching somewhere.
> 
> When you do the @EndpointInject uri, make sure you prepend with "mock" and 
> don't include anything pass the "?" in your uri. This wasn't obvious to me. 
> And again camel won't warn you if you get this wrong.
> 
> @DirtiesContext is a must otherwise you get strange behaviour once one test 
> starts failing.
> 
> Hope that helps.
> 
> On 12/06/2014, at 8:27 AM, Matt Raible <m...@raibledesigns.com> wrote:
> 
>> Thanks for the advice. I bought the book, read chapter 6 and I'm trying to 
>> use the advice builder. Chapter 6 talks about using mocks quite a bit, which 
>> seems useful in building a route, but not when it's already built.
>> 
>> My routes are configured with Spring and JavaConfig in a CamelConfig class. 
>> When I try to use CamelTestSupport as my parent class, the context doesn't 
>> have any route definitions in it. In other words, 
>> context.getRouteDefinitions() returns an empty list. How do I get 
>> CamelTestSupport to recognize my routes configured in Spring? Or is it 
>> possible to inject the context and template and use adviceWith w/o extending 
>> CamelTestSupport?
>> 
>> Thanks,
>> 
>> Matt
>> 
>> @RunWith(SpringJUnit4ClassRunner.class)
>> @ContextConfiguration(classes = CamelConfig.class)
>> public class FooRouteTests extends CamelTestSupport {
>> 
>>      @Test
>>      public void testAdvised() throws Exception {
>>              context.getRouteDefinition("routeId").adviceWith(context, new 
>> RouteBuilder() {
>>                      @Override
>>                      public void configure() throws Exception {
>>                              // intercept sending to mock:foo and do 
>> something else
>>                              interceptSendToEndpoint("sql:*")
>>                                              .skipSendToOriginalEndpoint()
>>                                              .to("log:foo")
>>                                              .to("mock:advised");
>>                      }
>>              });
>>              // we must manually start when we are done with all the advice 
>> with
>>              context.start();
>> 
>>              template.sendBody("direct:foo", "bar");
>> 
>>              getMockEndpoint("mock:advised").expectedMessageCount(1);
>>              assertMockEndpointsSatisfied();
>>      }
>> 
>>      @Override
>>      public boolean isUseAdviceWith() {
>>              // tell we are using advice with, which allows us to advice the 
>> route
>>              // before Camel is being started, and thus can replace sql with 
>> something else.
>>              return true;
>>      }
>> 
>> On Jun 11, 2014, at 12:16 PM, Claus Ibsen <claus.ib...@gmail.com> wrote:
>> 
>>> Hi
>>> 
>>> Yeah if you have Camel in Action book, read chapter 6.
>>> 
>>> And see bottom of this page
>>> http://camel.apache.org/testing
>>> 
>>> The advice builder is quite nifty and can "rework" the routes before 
>>> testing.
>>> 
>>> 
>>> On Wed, Jun 11, 2014 at 8:10 PM, Matt Raible <m...@raibledesigns.com> wrote:
>>>> Hello,
>>>> 
>>>> I have a route that looks as follows:
>>>> 
>>>>              from(uri)
>>>>                              .to("log:input")
>>>>                              
>>>> .recipientList(simple("direct:${header.operationName}"));
>>>>              from("direct:lookup")
>>>>                              .process(new Processor() {
>>>>                                      public void process(Exchange 
>>>> exchange) throws Exception {
>>>>                                              // grab parameters from 
>>>> request and set as headers for SQL statement
>>>>                                      }
>>>>                              })
>>>>                              
>>>> .recipientList(simple("sql:{{sql.lookup}}")).delimiter("false")
>>>>                              .to("log:output")
>>>>                              .process(new Processor() {
>>>>                                      public void process(Exchange 
>>>> exchange) throws Exception {
>>>>                                              List<HashMap> data = 
>>>> (ArrayList<HashMap>) exchange.getIn().getBody();
>>>> 
>>>>                                              // convert data to response
>>>> 
>>>>                                              
>>>> exchange.getOut().setBody(response);
>>>>                                      }
>>>>                              })
>>>> 
>>>> Is it possible to unit test this route and mock the data returned from the 
>>>> "sql" call? It'd love to be able to verify headers after the first 
>>>> .process, mock the results from the SQL call and verify the results from 
>>>> the 2nd .process method.
>>>> 
>>>> All of the routes I've developed with Camel so far make SQL calls, but I 
>>>> see SOAP calls in the future. I'll eventually need to mock SOAP calls as 
>>>> well.
>>>> 
>>>> Thanks,
>>>> 
>>>> Matt
>>> 
>>> 
>>> 
>>> -- 
>>> Claus Ibsen
>>> -----------------
>>> Red Hat, Inc.
>>> Email: cib...@redhat.com
>>> Twitter: davsclaus
>>> Blog: http://davsclaus.com
>>> Author of Camel in Action: http://www.manning.com/ibsen
>>> hawtio: http://hawt.io/
>>> fabric8: http://fabric8.io/
>> 
> 

Reply via email to