Is it possible to use adviceWith when using Spring/Camel's annotation support? 
I was originally trying to use this method, but had to extend CamelTestSupport 
and its context did not have my routes in it.

On Jun 11, 2014, at 11:39 PM, Claus Ibsen <[email protected]> wrote:

> Hi
> 
> You may want to use @MockEndpointsAndSkip so you do not call the SQL 
> component.
> 
> The camel-spring-test with the annotations was added to Camel later,
> after the book was published.
> 
> But you can find the annotations and more details here
> http://camel.apache.org/spring-testing.html
> 
> But as the SQL endpoint is dynamic calculated then its easier to use
> interceptSendToEndpoint and skip, as shown in the book on page 182
> with the advice with.
> 
> 
> 
> 
> On Thu, Jun 12, 2014 at 1:58 AM, Matt Raible <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 
>>>>>>> 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: [email protected]
>>>>>>> Twitter: davsclaus
>>>>>>> Blog: http://davsclaus.com
>>>>>>> Author of Camel in Action: http://www.manning.com/ibsen
>>>>>>> hawtio: http://hawt.io/
>>>>>>> fabric8: http://fabric8.io/
>>>>>> 
>>>>> 
>>>> 
>>> 
>> 
> 
> 
> 
> -- 
> Claus Ibsen
> -----------------
> Red Hat, Inc.
> Email: [email protected]
> 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