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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 
>>>>> 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: [email protected]
>>>>> Twitter: davsclaus
>>>>> Blog: http://davsclaus.com
>>>>> Author of Camel in Action: http://www.manning.com/ibsen
>>>>> hawtio: http://hawt.io/
>>>>> fabric8: http://fabric8.io/
>>>> 
>>> 
>> 
> 

Reply via email to