You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Matt Raible <ma...@raibledesigns.com> on 2014/06/11 20:10:26 UTC

Mocking SQL results in a route

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

Re: Mocking SQL results in a route

Posted by Matt Raible <ma...@raibledesigns.com>.
This looks like exactly what I was looking for. However, it doesn't seem to work. If I set a breakpoint in the "process" method, it's never called in my unit test. Here's what my test currently looks like:

@MockEndpoints("sql:.*")
public class DrugRouteTests {

	@Autowired
	CamelContext camelContext;

	@Produce
	ProducerTemplate template;

	@EndpointInject(uri = "mock:sql:*")
	MockEndpoint mockSql;

	@Test
	public void testMockSQLEndpoint() throws Exception {
		mockSql.whenAnyExchangeReceived(new Processor() {

			@Override
			public void process(Exchange exchange) throws Exception {
				exchange.getIn().setBody("sql output");
			}
		});

		template.sendBody("direct:foo", "bar");

		mockSql.expectedMessageCount(1);
		MockEndpoint.assertIsSatisfied(camelContext);
	}
}

In my logs, I see:

2014-06-12 07:49:08,405 [main           ] INFO  output                         - Exchange[ExchangePattern: InOnly, BodyType: java.util.ArrayList, Body: []]
2014-06-12 07:49:08,406 [main           ] INFO  MockEndpoint                   - Asserting: Endpoint[mock://sql:select...] is satisfied
2014-06-12 07:49:08,407 [main           ] INFO  MockEndpoint                   - Asserting: Endpoint[mock://sql:*] is satisfied

From this, you can see the output doesn't return anything from the SQL endpoint. Does the URI for the MockEndpoint need to be something else?

Thanks,

Matt

On Jun 11, 2014, at 7:41 PM, Minh Tran <da...@gmail.com> wrote:

> 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 <ma...@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 <da...@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 <ma...@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 <da...@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 <ma...@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 <cl...@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 <ma...@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: cibsen@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/
>>>>>> 
>>>>> 
>>>> 
>>> 
>> 
> 


Re: Mocking SQL results in a route

Posted by Minh Tran <da...@gmail.com>.
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 <ma...@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 <da...@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 <ma...@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 <da...@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 <ma...@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 <cl...@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 <ma...@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: cibsen@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/
>>>>> 
>>>> 
>>> 
>> 
> 


Re: Mocking SQL results in a route

Posted by Claus Ibsen <cl...@gmail.com>.
Hi

You can intercept from SQL * and then use a content based router or
recipient list or dynamic router or something, and use the exchange
property with key:
http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Exchange.html#INTERCEPTED_ENDPOINT

as it holds the endpoint that was intercepted.


You can mark an exchange to stop by setting the exchange property (or
header afair) with key
http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Exchange.html#ROUTE_STOP

and the value true.


On Thu, Jun 19, 2014 at 7:33 PM, Matt Raible <ma...@raibledesigns.com> wrote:
> Is it possible to mock the first and second sql endpoints using a sort of
> regular expression? The following seems to intercept all my "sql" endpoints.
>
> interceptSendToEndpoint("sql:*")
>
> As does this:
>
> interceptSendToEndpoint("sql:.*")
>
> I'd like to mock the first one and the 2nd one separately. The following
> seems to work, but I can see a situation where the SQL statements start the
> same and I just want to match on order of occurrence.
>
> interceptSendToEndpoint(""sql:select * from*")
>
> Also, is it possible to end the route when testing? For example, my route
> has 10 different steps and I want to test the first 5. Is it possible to
> stop and prevent proceeding after step 5 using adviceWith?
>
> Thanks,
>
> Matt
>
>
>
>
> On Fri, Jun 13, 2014 at 12:17 AM, Claus Ibsen <cl...@gmail.com> wrote:
>
>> Hi
>>
>> The weave methods of advice with has all kinds of addFirst / addList,
>> replace et all you can use
>> http://camel.apache.org/advicewith.html
>>
>> On Thu, Jun 12, 2014 at 6:48 PM, Matt Raible <ma...@raibledesigns.com>
>> wrote:
>> >
>> > On Jun 12, 2014, at 10:14 AM, Matt Raible <ma...@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 <cl...@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 <ma...@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 <cl...@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 <ma...@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 <cl...@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 <
>> matt@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 <da...@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 <ma...@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.minhster@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 <ma...@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.ibsen@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 <
>> matt@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: cibsen@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: cibsen@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: cibsen@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: cibsen@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: cibsen@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: cibsen@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/

Re: Mocking SQL results in a route

Posted by Matt Raible <ma...@raibledesigns.com>.
Is it possible to mock the first and second sql endpoints using a sort of
regular expression? The following seems to intercept all my "sql" endpoints.

interceptSendToEndpoint("sql:*")

As does this:

interceptSendToEndpoint("sql:.*")

I'd like to mock the first one and the 2nd one separately. The following
seems to work, but I can see a situation where the SQL statements start the
same and I just want to match on order of occurrence.

interceptSendToEndpoint(""sql:select * from*")

Also, is it possible to end the route when testing? For example, my route
has 10 different steps and I want to test the first 5. Is it possible to
stop and prevent proceeding after step 5 using adviceWith?

Thanks,

Matt




On Fri, Jun 13, 2014 at 12:17 AM, Claus Ibsen <cl...@gmail.com> wrote:

> Hi
>
> The weave methods of advice with has all kinds of addFirst / addList,
> replace et all you can use
> http://camel.apache.org/advicewith.html
>
> On Thu, Jun 12, 2014 at 6:48 PM, Matt Raible <ma...@raibledesigns.com>
> wrote:
> >
> > On Jun 12, 2014, at 10:14 AM, Matt Raible <ma...@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 <cl...@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 <ma...@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 <cl...@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 <ma...@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 <cl...@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 <
> matt@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 <da...@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 <ma...@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.minhster@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 <ma...@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.ibsen@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 <
> matt@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: cibsen@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: cibsen@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: cibsen@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: cibsen@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: cibsen@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/
>

Re: Mocking SQL results in a route

Posted by Claus Ibsen <cl...@gmail.com>.
Hi

The weave methods of advice with has all kinds of addFirst / addList,
replace et all you can use
http://camel.apache.org/advicewith.html

On Thu, Jun 12, 2014 at 6:48 PM, Matt Raible <ma...@raibledesigns.com> wrote:
>
> On Jun 12, 2014, at 10:14 AM, Matt Raible <ma...@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 <cl...@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 <ma...@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 <cl...@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 <ma...@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 <cl...@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 <ma...@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 <da...@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 <ma...@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 <da...@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 <ma...@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 <cl...@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 <ma...@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: cibsen@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: cibsen@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: cibsen@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: cibsen@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: cibsen@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/

Re: Mocking SQL results in a route

Posted by Matt Raible <ma...@raibledesigns.com>.
On Jun 12, 2014, at 10:14 AM, Matt Raible <ma...@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 <cl...@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 <ma...@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 <cl...@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 <ma...@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 <cl...@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 <ma...@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 <da...@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 <ma...@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 <da...@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 <ma...@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 <cl...@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 <ma...@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: cibsen@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: cibsen@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: cibsen@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: cibsen@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/
> 


Re: Mocking SQL results in a route

Posted by Matt Raible <ma...@raibledesigns.com>.
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);


On Jun 12, 2014, at 9:33 AM, Claus Ibsen <cl...@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 <ma...@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 <cl...@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 <ma...@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 <cl...@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 <ma...@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 <da...@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 <ma...@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 <da...@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 <ma...@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 <cl...@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 <ma...@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: cibsen@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: cibsen@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: cibsen@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: cibsen@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/


Re: Mocking SQL results in a route

Posted by Claus Ibsen <cl...@gmail.com>.
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 <ma...@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 <cl...@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 <ma...@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 <cl...@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 <ma...@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 <da...@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 <ma...@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 <da...@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 <ma...@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 <cl...@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 <ma...@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: cibsen@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: cibsen@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: cibsen@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: cibsen@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/

Re: Mocking SQL results in a route

Posted by Matt Raible <ma...@raibledesigns.com>.
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 <cl...@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 <ma...@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 <cl...@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 <ma...@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 <da...@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 <ma...@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 <da...@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 <ma...@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 <cl...@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 <ma...@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: cibsen@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: cibsen@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: cibsen@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/


Re: Mocking SQL results in a route

Posted by Claus Ibsen <cl...@gmail.com>.
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 <ma...@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 <cl...@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 <ma...@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 <da...@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 <ma...@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 <da...@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 <ma...@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 <cl...@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 <ma...@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: cibsen@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: cibsen@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: cibsen@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/

Re: Mocking SQL results in a route

Posted by Matt Raible <ma...@raibledesigns.com>.
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 <cl...@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 <ma...@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 <da...@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 <ma...@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 <da...@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 <ma...@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 <cl...@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 <ma...@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: cibsen@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: cibsen@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/


Re: Mocking SQL results in a route

Posted by Claus Ibsen <cl...@gmail.com>.
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 <ma...@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 <da...@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 <ma...@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 <da...@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 <ma...@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 <cl...@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 <ma...@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: cibsen@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: cibsen@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/

Re: Mocking SQL results in a route

Posted by Matt Raible <ma...@raibledesigns.com>.
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 <da...@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 <ma...@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 <da...@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 <ma...@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 <cl...@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 <ma...@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: cibsen@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/
>>>> 
>>> 
>> 
> 


Re: Mocking SQL results in a route

Posted by Minh Tran <da...@gmail.com>.
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 <ma...@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 <da...@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 <ma...@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 <cl...@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 <ma...@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: cibsen@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/
>>> 
>> 
> 


Re: Mocking SQL results in a route

Posted by Matt Raible <ma...@raibledesigns.com>.
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 <da...@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 <ma...@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 <cl...@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 <ma...@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: cibsen@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/
>> 
> 


Re: Mocking SQL results in a route

Posted by Minh Tran <da...@gmail.com>.
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 <ma...@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 <cl...@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 <ma...@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: cibsen@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/
> 


Re: Mocking SQL results in a route

Posted by Matt Raible <ma...@raibledesigns.com>.
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 <cl...@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 <ma...@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: cibsen@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/


Re: Mocking SQL results in a route

Posted by Claus Ibsen <cl...@gmail.com>.
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 <ma...@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: cibsen@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/