camel-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Minh Tran <darth.minhs...@gmail.com>
Subject Re: Mocking SQL results in a route
Date Wed, 11 Jun 2014 23:08:30 GMT
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 <matt@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/
> 


Mime
View raw message