practical programmer
practical programmer

Reputation: 1648

How to mock Grails Services in Camel Production Route unit tests

I need to write Unit tests for production routes in Grails which use Services referenced by Camel bean component. My requirement is neither to change nor to copy existing routes in test.

Problem is to somehow mock Service bean and add it to Camel registry.

I was able to do this using 'bind' method on 'context.registry.registry' object. Is there any functionality to do that in more safe way? Camel version is 2.10, Grails 2.1

Route is:

from('direct:validate').to('bean:camelService?method=echo')

CamelService is just simple class:

package com

class CamelService {
    def echo(text) {
        println "text=$text"
        text
    }
}

Test is following (route copied only to make question simpler):

package com

import grails.test.mixin.*
import org.apache.camel.builder.RouteBuilder
import org.apache.camel.test.junit4.CamelTestSupport

@TestFor(CamelService)
class RouteTests extends CamelTestSupport {

    @Override
    protected RouteBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder() {
            @Override
            public void configure() throws Exception {
                from('direct:validate').to('bean:camelService?method=echo')
            }
        };
    }

    void testMockBean() throws Exception {
        context.registry.registry.bind 'camelService', service
        def result = template.requestBody('direct:validate', 'message')
        assert result != null
        assert result == 'message'
    }
}

Upvotes: 2

Views: 614

Answers (2)

Claus Ibsen
Claus Ibsen

Reputation: 55555

Camel allows you to plugin any custom registry you want, and out of the box it uses a Jndi based registry, which is why you can bind a service to it with the code example. An alternative is to use a SimpleRegistry which is just a Map, so you can put a service into the registry using the put method from the Map. You would then need to override createCamelContext method from the CamelTestSupport class and pass in the SimpleRegistry to the constructor of DefaultCamelContext.

Anyway your code is safe as long you use the non-Spring CamelTestSupport class, as its using the JNDI based registrry out of the box. If you use CamelSpringTestSupport, then its a spring based registry, and you would need to use the spring app context to add your bean to it.

Upvotes: 1

cexbrayat
cexbrayat

Reputation: 18422

You can inject your components using CamelSpringtestSupport rather than CamelTestSupport as your base class.

Reading the documentation on Spring Test will help you for sure, and you might find interesting to use mock in your tests.

Anyway, you can build a custom context for your test, containing your bean's declaration and load it in the test.

public class RouteTests  extends CamelSpringTestSupport {

    @Override
    protected AbstractApplicationContext createApplicationContext() {
        return new ClassPathXmlApplicationContext("route-test-context.xml");
    }

    @Test
    public void testMockBean(){
         //...
    }
}

route-test-context.xml

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://camel.apache.org/schema/cxf" xmlns:camel="http://camel.apache.org/schema/spring"
xsi:schemaLocation="
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://camel.apache.org/schema/spring 
     http://camel.apache.org/schema/spring/camel-spring.xsd">

     <bean id="service" ref="com.CamelService"/>
     <camelContext xmlns="http://camel.apache.org/schema/spring">
          <package>com</package>
     </camelContext>
</beans>

Upvotes: 0

Related Questions