How to test your ESB services

Now that you have created ESB services, how do you test them? Actions themselves are generally easily testable—create a message with some test data, and you can simulate the effect of executing a single action. What is more complex is integration testing—testing your complete action chain and testing your service through the listeners and providers that you set up within your configuration file. In the following section, we'll discuss how to perform this sort of integration test so that you can add it into your build process.

Testing a single action

Actions alone are generally easily testable. You can create a message with some test data, invoke the action's process method upon the message, and then make comparisons with the resulting message or check for exceptions.

package org.jboss.soa.esb.samples.quickstart.helloworld;
import junit.framework.TestCase;
import org.jboss.soa.esb.actions.SystemPrintln;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.format.MessageFactory;

public class SimpleJUnitTestCase extends TestCase {
    private static final String MESSAGE_STRING = "helloworld";
    public void testSystemPrintln() throws Exception {
        Message message = MessageFactory.getInstance().getMessage();
        message.getBody().add(MESSAGE_STRING);
        ConfigTree config = new ConfigTree("config");
        SystemPrintln spl = new SystemPrintln(config);
        Message result = spl.process(message);
        String resultString = (String) result.getBody().get();
        assertEquals(MESSAGE_STRING, resultString);
    }
}

This code gives the following output:

junit:
    [junit] Running org.jboss.soa.esb.samples.quickstart.helloworld.SimpleJUnitTestCase
    [junit] Testsuite: org.jboss.soa.esb.samples.quickstart.helloworld.SimpleJUnitTestCase
    [junit] Message structure:
    [junit] [helloworld].
    [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.4 sec
    [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.4 sec
    [junit] ------------- Standard Output ---------------
    [junit] Message structure:
    [junit] [helloworld].
    [junit] ------------- ---------------- ---------------
    [junit]
    [junit] Testcase: testSystemPrintln took 0.198 sec

BUILD SUCCESSFUL
Total time: 2 seconds

AbstractTestRunner

Do you want to be able to execute your action chain via the service invoker in tests? AbstractTestRunner allows you to do that, without the overhead of starting a container. In order to use AbstractTestRunner, you specify your ESB configuration files (jboss-esb.xml and jbossesb-properties.xml), and AbstractTestRunner will take care of setting up the registry and controller.

AbstractTestRunner is included inside the test-util.jar in the ESB binary distribution. If you are using ant, simply add it to your <junit/> classpath. If you are using Maven, install it locally into your repository:

mvn install:install-file -Dfile=test-util.jar -DgroupId=org.jboss.soa.esb  -DartifactId=test-util -Dversion=4.10 -Dpackaging=jar

Once installed, add org.jboss.soa.esb:test-util as a dependency with test scope. The following HelloWorldTest class makes an anonymous instance of the AbstractTestRunner class, invokes the run() method, and sets the service config to the helloworld-jboss-esb.xml configuration.

The test method is where we use ServiceInvoker. ServiceInvoker invokes the FirstServiceESB:SimpleListener service with a message containing "helloworld". The test method is invoked when the testRunner object executes the run() method.

package org.jboss.soa.esb.samples.quickstart.helloworld;
import junit.framework.TestCase;
import org.jboss.soa.esb.testutils.AbstractTestRunner;
import org.jboss.soa.esb.client.ServiceInvoker;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.format.MessageFactory;
import org.jboss.soa.esb.actions.ActionProcessingException;

public class HelloWorldTest extends TestCase {
    public void test_async() throws Exception {
        AbstractTestRunner testRunner = new AbstractTestRunner() {
            public void test() throws Exception {
                ServiceInvoker invoker =new ServiceInvoker("FirstServiceESB","SimpleListener");
                Message message =MessageFactory.getInstance().getMessage();
                message.getBody().add("helloworld");

                message = invoker.deliverSync(message, 10000);

               // Insert code here to verify your results
               assertEquals("helloworld", message.getBody().get());
           }
        }.setServiceConfig("helloworld-jboss-esb.xml");

        testRunner.run();
    }
}

Below is the configuration for our AbstractTestRunner example. The following action chain prints the message using the SystemPrintln action and stores the message in TestMessageStore:

<?xml version = "1.0" encoding = "UTF-8"?>
<jbossesb xmlns="http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsdhttp://anonsvn.jboss.org/repos/labs/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd"
          parameterReloadSecs="5">

  <providers>
    <jms-provider name="JBossMQ"connection-factory="ConnectionFactory">
      <jms-bus busid="quickstartGwChannel">
        <jms-message-filter dest-type="QUEUE"
             dest-name="queue/quickstart_helloworld_Request_gw"/>
      </jms-bus>
      <jms-bus busid="quickstartEsbChannel">
        <jms-message-filter dest-type="QUEUE"
             dest-name="queue/quickstart_helloworld_Request_esb"/>
      </jms-bus>

    </jms-provider>
  </providers>

  <services>
    <service category="FirstServiceESB" 
             name="SimpleListener" 
             description="Hello World">
      <listeners>
        <jms-listener name="JMS-Gateway"
                      busidref="quickstartGwChannel"
                      is-gateway="true"/>
        <jms-listener name="helloWorld"
                      busidref="quickstartEsbChannel"
      </listeners>
      <actions mep="OneWay">
        <action name="action1" 
                class="org.jboss.soa.esb.samples.quickstart.helloworld.MyJMSListenerAction" 
                process="displayMessage"/>
        <action name="action2"
                class="org.jboss.soa.esb.actions.SystemPrintln">
          <property name="printfull" value="false"/>
        </action>
        <!-- The next action is for ContinuousIntegration testing -->
        <action name="testStore"
                class="org.jboss.soa.esb.actions.TestMessageStore"/>
      </actions>
    </service>
  </services>
</jbossesb>

AbstractTestRunner is a great way to test your actions in combination with others in an action chain, but if you want to use your full ESB configuration—using providers and listeners—you'll have to run an in-container test (see the Arquillian section).

TestMessageStore

If you want to test the aggregated results of your action chain, you have to store the result message somewhere. JBoss ESB provides an org.jboss.esb.actions.TestMessageStore action which logs the message result and any exceptions thrown.

TestMessageStore is very important for the situation in which you want to test in a container against your deployed services. In this situation, you need to be able to receive the exceptions in the chain and the result message, the TestMessageStore action allows you to store both. In the tests that validate the quickstart examples within the JBoss ESB project, a small MBean is created which stores a TestMessageStoreSink that can be queried through JMX. This allows the tests to check results on the server itself without having to worry about receiving the results from a file or checking the server log file, where timing or permissions issues can lead to tests going astray.

In order for you to access TestMessageStore, you most likely need to reproduce the sort of MBean that JBoss ESB uses internally for its integration tests. Download the esb source and examine:

  • qa/quickstarts/src/org/jboss/soa/esb/server/QuickstartMessageStoreImplMBean.java
  • qa/quickstarts/src/org/jboss/soa/esb/server/QuickstartMessageStoreImpl.java
  • qa/quickstarts/src/org/jboss/soa/esb/server/QuickstartMessageStore.java
  • qa/quickstarts/resources/server/META-INF/jboss-service.xml

If you compile the three sources and jboss-service.xml into an SAR, you can deploy it and then start querying the MBean for results once you have invoked your service. The qa/quickstarts/src/org/jboss/soa/esb/quickstart/test/ tests within the JBoss ESB source are very good examples of how to access the MBean and retrieve message results.

Once that is working, the TestMessageStore action is inserted in the action chain of your jboss-esb.xml configuration.

<actions>
  <action name="action2"
          class="org.jboss.soa.esb.actions.SystemPrintln">
    <property name="printfull" value="false"/>
</action>
<!-- The next action is for Continuous Integration testing -->
  <action name="testStore"
          class="org.jboss.soa.esb.actions.TestMessageStore"/>
</actions>

After invoking your service, you should see your action chain execute, and a log message that shows that your message was added into TestMessageStoreSink (output from the helloworld quickstart shown):

01:17:44,937 INFO  [STDOUT] TestMessageStoreSink: Adding message: Hello World

Arquillian

Once you build an ESB archive, you also want to test it. Unit tests are excellent for testing your business logic, but you also want to test how your services work when your archive is deployed to a container. What's the easiest way to deploy, run tests, and then subsequently undeploy all of your test resources? All sorts of issues lurk here—how do you tell whether the container or your archive is fully deployed and ready to test? How do you ensure your archive and resources are fully removed and undeployed by the time your next test runs?

Arquillian (http://www.jboss.org/arquillian/) is a test framework that focuses on making container deployment very easy within your tests. It allows you to test within an embedded or a remote container. In terms of testing JBoss ESB, Arquillian only supports testing services in a remote container, but it is a big advantage in integration testing your ESB archives because it manages the container lifecycle for you.

In this first example, we have a previously built ESB archive. In order for Arquillian to deploy it, it needs to be created through ShrinkWrap (http://www.jboss.org/shrinkwrap), so we wrap it in a file, we import it as a ZipFile object and create it as a JavaArchive object. Arquillian will now deploy it during the execution of the test.

package org.jboss.soa.esb;

import java.io.File;
import java.util.zip.ZipFile;

import org.jboss.arquillian.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.importer.ZipImporter;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(Arquillian.class)
public class ArquillianBinaryTest {
    private static final String ESB_LOCATION ="/src/jbossesb/product/samples/quickstarts/helloworld_book/build/QuickStartHelloWorld.esb";

    @Deployment(testable=false)
    public static JavaArchive createTestArchive() throws Exception {
        File file;
        ZipFile existingZipArchive = null;
        file = new File(ESB_LOCATION);
        existingZipArchive = new ZipFile(file);
        return ShrinkWrap.create(JavaArchive.class, "test.esb")
              .as(ZipImporter.class)
              .importZip(existingZipArchive)
              .as(JavaArchive.class); 
    }

    @Test
    public void testMethod() throws Exception {
       // Insert your test logic and execution here
   }
}

The second Arquillian example shows how to create our deployment as a ShrinkWrap archive. We import the necessary configuration and descriptor files as well as a custom action, and then the resulting archive is deployed through ShrinkWrap. This is a great option to take if you want to test alternative configurations.

package org.jboss.soa.esb;
import java.io.File;

import org.jboss.arquillian.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.FileAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.jboss.soa.esb.samples.quickstart.helloworld.MyJMSListenerAction;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(Arquillian.class)
public class ArquillianTest {


    @Deployment(testable=false)
    public static JavaArchive createTestArchive() throws Exception {
        return ShrinkWrap.create(JavaArchive.class, "test.esb")
             .add(new FileAsset(new File("jbm-queue-service.xml")),"jbm-queue-service.xml")
             .addClass(MyJMSListenerAction.class)
             .addAsManifestResource("jboss-esb.xml")
             .addAsManifestResource("deployment.xml");
    }

    @Test
    public void testMethod() throws Exception {
        // Insert your test logic and execution here
    }
}

Cargo

Cargo (http://cargo.codehaus.org/) is an alternative to using Arquillian. Cargo is a set of build tools which allow you to control a Java container as part of your Maven or ant build cycle. You can start a container pre-test, deploy your ESB archive, and then run tests, either using ServiceInvoker or one the listeners that you have set up (file, JMS, and so on) to test your application.

There are multiple ways you can deploy your newly built ESB archive to the Cargo-controlled container that you are testing. You can copy the archive directly into the deploy directory as part of the build, and then clean up by deleting it once your tests are finished. Alternatively if you are using Maven, you can use the jboss-maven-plugin's jboss:hard-deploy/hard-undeploy goal to copy it to the deploy directory. Finally, you can use Cargo to either locally or remotely deploy to your container using the cargo:deploy goal.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.134.78.106