siliconsenthil

Apache Camel with Scala: Testing Styles

Scala with Camel is a very powerful combination for integration. Camel has fantastic support for testing. It’s very easy and useful to test-drive the integration. Following are few styles when it comes to testing camel with scala.

Use CamelTestSupport, JUnit style

CamelTestSupport already has JUnit annotations to run do setup and teardown in JUnit test suite. The simplest way to get started is to use this with ScalaTest. ScalaTest already has JUnitSuite trait to have JUnit style tests. This is documented here(see Testing section).

Extending CamelTestSupport

If you dont like the JUnit style and wanna follow any other styles ScalaTest supports, you can create a base test support class that looks like below.


class CustomCamelFlatTestSupport extends CamelTestSupport with BeforeAndAfterAll with FlatSpec{

  override def beforeAll() {
    setUp()
  }

  override def afterAll() {
    tearDown()
  }
}

We are following FlatSpec style of ScalaTest.

class YourRouteSpec extends CustomCamelFlatTestSupport{
  override def createRouteBuilder = YourRouteBuilder.buildRoute

  before {
    interceptTimer()
  }

  private def interceptTimer() {
    context.getRouteDefinition("YourRouteName").adviceWith(context, new AdviceWithRouteBuilder {
      def configure() {
        replaceFromWith("direct:testEndpoint")
      }
    })
  }

  "Your Route" should "do something useful" in {
    template.sendBody("direct:testEndpoint", "Some body")
    //Assert some behaviour
    }
}

We override the createRouteBuilder with the route we wanna test. There might be needs to intercept routes for testing purpose.

But, if wanna have different routes or different interceptors in every test, this style would not suite.

CamelTestHelper trait

With this style you can pass differnt builders and different interceptors and the test code is a block that get the test support.

Create a trait like below

trait CamelTestHelper{
  def withCamelTestSupport(routeBuilder: RouteBuilder, interceptor:(ModelCamelContext => Unit) = identity(_))(testWithCamelSupport: CamelTestSupport => Any){
    new CamelTestSupport{
      override def createRegistry = {
        val registry = super.createRegistry
        //Put entries to registry if needed.
        registry
      }
      override def createRouteBuilder() = routeBuilder
      setUp()
      interceptor(context)
      testWithCamelSupport(this)
      tearDown()
    }
  }
}

A typical way to use the trait in test would be,

  "Your Route" should "do something useful" in {
    val directEndpoint = "direct:testEndpoint"

    val testRouteBuilder = new RouteBuilder {
      from("timer:doesNotMatter").routeId("OurRoute").to("file:/some/path"))
    }.builder

    def interceptor(context: ModelCamelContext) {
      context.getRouteDefinition("OurRoute").adviceWith(context, new AdviceWithRouteBuilder {
        def configure() {
          replaceFromWith(directEndpoint)
        }
      })
    }

    withCamelTestSupport(testRouteBuilder, interceptor){ testSupport =>
        testSupport.template.sendBody(directEndpoint, "Some content")
        //Assert files exists @ /some/path
      }
    }
  }

With this style we get full flexibility about testing routes.