Hi

Is it the @AdviceWith you are looking for ?
http://camel.apache.org/spring-testing.html

On Thu, Jun 12, 2014 at 4:30 PM, Matt Raible <m...@raibledesigns.com> wrote:
> 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 <claus.ib...@gmail.com> 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 <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/
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>>
>>
>> --
>> 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/
>



-- 
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