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