Awesome, you got that bit working.

To get the mock end point to behave a certain way once it receives an exchange, 
you can do something like

endpoint.whenAnyExchangeReceived(new Processor() {

                        @Override
                        public void process(Exchange exchange) throws Exception 
{
                                exchange.getIn().setBody("sql output");
                        }
                });

The regex isn't quite correct leaving it as sql:* because that means it will 
match zero or more ":". So let's say you had the following endpoints in your 
routes

1. sql:select blah from foo
2. sql1:select blah from foo
3. sql2:select blah from foo

If you had used regex "sql:*" then it would match all 3 endpoints. If you had 
used "sql:.*", it would only match the first one. The second one is more exact.

To help with debugging routes, I like to enable tracing, it will dump out the 
headers and bodies of the exchange as it passes through each individual 
endpoint. There's a setter on the camel context. 



On 12/06/2014, at 9:58 AM, Matt Raible <m...@raibledesigns.com> wrote:

> Nope, my routes are defined using the Java DSL, not XML. Changing from:
> 
> @ContextConfiguration(classes = CamelConfig.class)
> 
> To:
> 
> @ContextConfiguration(loader = CamelSpringDelegatingTestContextLoader.class, 
> classes = CamelConfig.class)
> 
> Solved my problem.
> 
> I don't know if the regex needs to change. Using @MockEndpoints("sql:*"), I 
> see the following in my logs:
> 
> 2014-06-11 17:53:35,388 [main           ] INFO  output                        
>  - Exchange[ExchangePattern: InOnly, BodyType: java.util.ArrayList, Body: []]
> 2014-06-11 17:53:35,389 [main           ] INFO  MockEndpoint                  
>  - Asserting: Endpoint[mock://sql:select...] is satisfied
> 2014-06-11 17:53:35,390 [main           ] INFO  MockEndpoint                  
>  - Asserting: Endpoint[mock://sql:*] is satisfied
> 
> It looks like it's working, but the test is failing:
> 
> java.lang.AssertionError: mock://sql:* Received message count. Expected: <1> 
> but was: <0>
> 
> So now I want to do two things: 1) understand why my mockSQL endpoint is not 
> receiving a message and 2) make the mock SQL endpoint return an ArrayList of 
> items so I can test my processing logic. 
> 
> On Jun 11, 2014, at 5:46 PM, Minh Tran <darth.minhs...@gmail.com> wrote:
> 
>> It appears to me like you have your routes defined in xml and not actually 
>> in JavaConfig? In that case, you can simplify your configuration even 
>> further and not refer to your JavaConfig class like this
>> 
>> @RunWith(CamelSpringJUnit4ClassRunner.class)
>> @ContextConfiguration(loader = CamelSpringDelegatingTestContextLoader.class, 
>> locations = { "classpath:/path/to/xml" })
>> @DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
>> @MockEndpointsAndSkip("sql:.*")
>> public class FooRouteTests
>> 
>> No need to extend any class.
>> Also your regex has to be "sql:.*" and not "sql:*" They mean two different 
>> things in regex.
>> 
>> On 12/06/2014, at 9:32 AM, Matt Raible <m...@raibledesigns.com> wrote:
>> 
>>> 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