Camel and Test

This post will highlight some guideline for working with Camel and test. This is more of an introduction than covering any advanced topics. As always the starting point should be the documentation so have a look at here .

Basically in Camel you have a test framework. This framework allows you to do some very important functionality.

  1. You can mock endpoints that are not available or not built yet. This means if you want to connect to some http endpoint which is not yet available you can simply mock it and inject the expected reply instead.
  2. You can intercept messages before they reach an endpoint and do something with them.
  3. You can do usual junit stuff like assertions for number of messages etc or comparing expected output with actual output.

There is more but these are the basics.

So usually you start with unit tests, then move to higher order tests. I will cover unit test and how to perform integration test using Cucumber-JVM to write Given-When-Then features which can be written b non-developers.

Unit test

Here is a very simple method:

@Test
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import org.apache.camel.Exchange;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.impl.JndiRegistry;
import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.test.blueprint.CamelBlueprintTestSupport;
import org.junit.Test;

public class TestFileTransfer extends CamelBlueprintTestSupport {

@Override
public void doPreSetup() throws Exception {
System.setProperty(”org.apache.aries.blueprint.synchronous”, Boolean.TRUE.toString());
}

@Override
protected String getBlueprintDescriptor() {
return ”/OSGI-INF/blueprint/filetransfer.xml”;
}

@Test
public void testPutFile(String body, String endpoint) throws Exception {
this.setUp();
template.sendBody(endpoint,body);
Thread.sleep(2000);
assertFileNotExists(endpoint);
}

@Test
public void testFileHasMoved(String path) throws Exception {

assertFileExists(path);
}

}

So let me break the unit test class so you can create your own:

  1. You need to extend the CamelBlueprintTestSupport if you are testing blueprint otherwise CamelTestSupport is sufficient.
  2. If it is blueprint you need the getBluePrintDescriptor method to let your test class know where to find your blueprint configuration.
  3. Finally you have your test methods where you can test writing some data to a file and let camel pick it up. The second test asserts that the file has been picked up.

This is how Camel tests usually work. Now there is more you can add such as debug logs, interceptions and replacing endpoints etc. But you can find more information in the documentation on this.

Now sometimes you are part of a team and there are testers who write GIVEN-WHEN-THEN scenarios to cover business requirements. You can call these scenario or integration tests. The name is not that important. But essentially you have feature files where you write your scenarios in G-W-T format. Then you have java classes that parse them and execute tests based on this.

Wouldn’t it be good to have scenario tests for Camel as well? Well you can.

First have a read through here:

http://stackoverflow.com/questions/33568649/camel-blueprint-testing-and-cucumber

The framework I will use is Cucumber-JVM. Cucumber is used to write scenario tests for Javascript and now there is library for java as well. The main parts are as follows:

  1. Write your feature files in G-W-T format and put them in a folder in your classpath.
  2. Write a Cucumber runner class.
  3. Write your Camel test class that includes the line this.setUp(); . This is important because Camel uses the JUNIT runner whereas Cucumber has its own Runner. Without that line it wouldn’t work.
  4. Finally run your Cucumber runner class and look at the logs. It should say xxx scenarios run and number of scenarios succeeded or similar. In the target folder there will be a html page that show this in a nice way.
Feature file

So here is a simple feature file. In real world feature file you have feature descriptions etc but I am simplifying here. You can save it as filetransfer.feature and put in a folder in your project in Eclipse or your editor.

Scenario: Hello world file transfer
Given an input file
When client puts the file in the input directory

Then the integration should move the file to the output directory

Cucumber runner class


import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;

import org.apache.camel.Exchange;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.test.blueprint.CamelBlueprintHelper;
import org.apache.camel.test.blueprint.CamelBlueprintTestSupport;
import org.junit.Test;
import org.junit.internal.runners.JUnit4ClassRunner;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(Cucumber.class)
@CucumberOptions(monochrome=true,
format={ ”pretty”, ”html:target/cucumber”},
features = ”C:/Users/Developer/workspace_camel/IntegrationScenarioTest/src/test/resources/cucumber/filetransfer.feature”)

public class CucumberRunner {

}

The main thing notice is I am referring to the feature file and asking it to create the html output and that it runs with the Cucumber runner. The class itself contains nothing.

Cucumber scenario java methods

Now we need to write the java class containing the methods to match the scenarios in the feature file. This is an example class for this.

import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import org.apache.camel.Exchange;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.test.blueprint.CamelBlueprintTestSupport;
import org.junit.internal.runners.JUnit4ClassRunner;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import cucumber.api.java.Before;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class FileTransferScenarioTest {

FileTransferCamelRunner filetransfer = new FileTransferCamelRunner();
StringBuilder fileData= new StringBuilder(”This is just some text.”);
StringBuilder endpoint= new StringBuilder();

@Given(”^an input file$”)
public void an_input_file() throws Throwable {
endpoint.append(”file:C:/Camel/input?fileName=input.txt”);
}

@When(”^client puts the file in the input directory$”)
public void client_puts_the_file_in_the_input_directory() throws Throwable {
filetransfer.testPutFile(fileData.toString(), endpoint.toString());
}

@Then(”^the integration should move the file to the output directory$”)
public void the_integration_should_move_the_file_to_the_output_directory() throws Throwable {
String outputPath = ”C:/Camel/output/input.txt”;
filetransfer.testFileHasMoved(outputPath);
}

}

As you can see the methods are matched using Given, When and Then and regex is used to match the text sentences in the scenarios to the actual java methods. Each part should correspond to some action. For example ”the integration should move the file to the output folder” calls the method testFileHasMoved in the Camel test class to check that the file has actually moved.

Camel test classes

Finally we have the Camel test classes to tie it all together.

import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import org.apache.camel.Exchange;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.impl.JndiRegistry;
import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.test.blueprint.CamelBlueprintTestSupport;
import org.junit.Test;

public class FileTransferCamelRunner extends CamelBlueprintTestSupport {

@Override
public void doPreSetup() throws Exception {
System.setProperty(”org.apache.aries.blueprint.synchronous”, Boolean.TRUE.toString());
}

@Override
protected String getBlueprintDescriptor() {
return ”/OSGI-INF/blueprint/filetransfer.xml”;
}

@Test
public void testPutFile(String body, String endpoint) throws Exception {
this.setUp();
template.sendBody(endpoint,body);
Thread.sleep(2000);
assertFileNotExists(endpoint);
}

@Test
public void testFileHasMoved(String path) throws Exception {

assertFileExists(path);
}

}

The most important part is the line ”   this.setUp();” in the method testPutFile which is the first method that gets called. It ensures that the Camel runtime is started in a successful way even though we are using the Cucumber Runner. Without this line the connection from Cucumber to Camel would not work. All you need to do then is run the Cucumber runner class as a JUNIT test and view the output.

Annonser

Kommentera

Fyll i dina uppgifter nedan eller klicka på en ikon för att logga in:

WordPress.com Logo

Du kommenterar med ditt WordPress.com-konto. Logga ut / Ändra )

Twitter-bild

Du kommenterar med ditt Twitter-konto. Logga ut / Ändra )

Facebook-foto

Du kommenterar med ditt Facebook-konto. Logga ut / Ändra )

Google+ photo

Du kommenterar med ditt Google+-konto. Logga ut / Ändra )

Ansluter till %s