On Jun 12, 2014, at 10:14 AM, Matt Raible <m...@raibledesigns.com> wrote:
> OK, I got that to work by using @UseAdviceWith. Here's my @Before method that > sets everything up and returns SQL results: > > static List<Map> results = new ArrayList<Map>() {{ > add(new HashMap<String, String>() {{ > put("foo", "bar"); > }}); > }}; > > @Before > public void before() throws Exception { > camelContext.setTracing(true); > > ModelCamelContext context = (ModelCamelContext) camelContext; > RouteDefinition route = context.getRouteDefinition("myRouteId"); > route.adviceWith(context, new RouteBuilder() { > @Override > public void configure() throws Exception { > > interceptSendToEndpoint("sql:*").skipSendToOriginalEndpoint().process(new > Processor() { > @Override > public void process(Exchange exchange) > throws Exception { > > exchange.getOut().setBody(results); > } > }); > } > }); > camelContext.start(); > } > > Now in my route, I want to verify the final results. Since it's a .process() > call, there's no endpoint name to look for and mock. > > .to("sql:select * ...") > .to("log:output") > .process(new Processor() { > public void process(Exchange exchange) throws Exception { > List<HashMap> data = (ArrayList<HashMap>) > exchange.getIn().getBody(); > // create response from data > exchange.getOut().setBody(response); > } > }); > > Is it possible to add a "mock:result" at the end, after .process()? > > I tried the following, but no messages are received. > > @MockEndpoints // added to class > > @EndpointInject(uri = "mock:result") > protected MockEndpoint result; > > @Test > ... > result.expectedMessageCount(1); > > template.sendBody ... > > MockEndpoint.assertIsSatisfied(camelContext); > Nevermind, figured it out: // No reason for @MockEndpoints on class @EndpointInject(uri = "mock:result") MockEndpoint result; @Before public void before() throws Exception { ... route.adviceWith(context, new RouteBuilder() { .... }); route.to(result); camelContext.start(); } @Test public void testMockSQLEndpoint() throws Exception { result.expectedMessageCount(1); Thanks for all the help! Matt > > On Jun 12, 2014, at 9:33 AM, Claus Ibsen <claus.ib...@gmail.com> wrote: > >> Hi >> >> @ EndpointInject does not match wildcards. >> >> Do this as I said before in my previous mail >> >> 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 4:47 PM, Matt Raible <m...@raibledesigns.com> wrote: >>> Possibly. If I have the following annotations on my class: >>> >>> @MockEndpoints("sql:.*") >>> @UseAdviceWith >>> >>> And I mock the SQL endpoint: >>> >>> @EndpointInject(uri = "mock:sql:*") >>> MockEndpoint mockSql; >>> >>> Then I try to set the mocked endpoint's results: >>> >>> @Test >>> public void testMockSQLEndpoint() throws Exception { >>> mockSql.whenAnyExchangeReceived(new Processor() { >>> @Override >>> public void process(Exchange exchange) throws >>> Exception { >>> exchange.getIn().setBody("sql output"); >>> } >>> }); >>> camelContext.start(); >>> >>> The mock SQL output is still not set. >>> >>> On Jun 12, 2014, at 8:40 AM, Claus Ibsen <claus.ib...@gmail.com> wrote: >>> >>>> 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/ >>> >> >> >> >> -- >> 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/ >