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