Testing SwitchYard Services

Testing SwitchYard Services is dead simple!  It involves two simple steps that will be very familiar to all Java Developers:

 

  1. Implement the Service.
  2. Implement a Unit Test for the Service.

 

Implementing a Service

At present, the easiest way to implement a Service in SwitchYard is via the Bean component.  For more details, see Creating Services with Bean Component.

 

Implementing a Unit Test for a Service

First step is to add the switchyard-test module to your application test classpath.  In maven, this can be done by adding the dependency artifact as follows.

 

<dependency>
    <groupId>org.switchyard</groupId>
    <artifactId>switchyard-test</artifactId>
    <version>[release-version]</version> <!-- e.g. "0.1.0.M1" -->
    <scope>test</scope>
</dependency>

 

After that, extend one of the abstract SwitchYard TestCase classes:

 

  • SwitchYardTestCase:  Base TestCase.  Creates a SwitchYard test ServiceDomain and provides utility methods for registering and invoking Services in that test ServiceDomain.
  • SwitchYardCDITestCase:  Extends SwitchYardTestCase, adding launch code for the Weld CDI container, as well as auto-registration of bean Service implementations found on the module classpath.  This TestCase is used for testing Bean Component Services.

 

Using SwitchYardTestCase

In reality, most/all developers will extend the SwitchYardCDITestCase class (or other extentions of SwitchYardTestCase, should they come into existence).  However, it is useful to highlight what this base TestCase does.

 

SwitchYardCDITestCase provides the following services:

 

  1. Bootstraps a basic test SwitchYard ServiceDomain for your test methods.
  2. Provides utility methods that allow you to:
    • Get the underlying SwitchYard test ServiceDomain instance (getServiceDomain()).
    • Register MockHandler ExchangeHandlers for given service names (registerInOutService(), registerInOnlyService() etc).
    • Create an Invoker instance for an operation exposed by a Service registered in the test ServiceDomain.  See below for more details on the Invoker class.
    • Register Transformer instances on the test ServiceDomain.
  3. Destroys and cleans up the ServiceDomain on test tear-down.

 

See the next section for specific examples.

 

Using SwitchYardCDITestCase

Since the Bean Component model is the default Service programming model in SwitchYard, the SwitchYardCDITestCase will be the TestCase that most Service developers will be extending.

 

So the basic workflow is really simple.  First you would simply create the Bean Service (see Creating Services with Bean Component):

 

@Service(SimpleService.class)
public class SimpleServiceBean implements SimpleService {
   public String sayHello(String message) {
      System.out.println("*** Hello message received: " + message);
      return "Hi there!!";
   }  
}
 
public interface SimpleService {
   String sayHello(String message);
}

 

Then create the TestCase by extending SwitchYardCDITestCase:

 

public class SimpleServiceTest extends SwitchYardCDITestCase {

    @Test
    public void invokeRequestResponseProviderWithInOut() {
        // Create an invoker for invoking the target Service Operation and getting 
        // the response back...
        Invoker invoker = newInvoker("SimpleService.sayHello");
        Message response = invoker.sendInOut("Hello SimpleService!!");

        // Make assertions on the response Message payload...
        Assert.assertEquals("Hi there!!", response.getContent());
    }
}

 

And that is it !! 

 

The SwitchYardCDITestCase bootstrapping code, plus the Invoker class are doing all the heavy lifting for your test.  You don't need to worry about creating a SwitchYard ServiceDomain, registering Services (CDI bean services are automatically registered as Services in the test ServiceDomain), or how to wire together the components needed for making an invocation on the Service's Operations.  This grunt work is all taken care of for you.  Your test code can just concentrate on testing your Service implementation.

 

See the section below for more details on the Invoker class.

 

Invoker

Unit test methods can create Invoker instances, which allow the test method make invocations on a Service Operation of one of the services registered with the TestCase's SwitchYard ServiceDomain.

 

Creating an Invoker instance is done by simply calling the newInvoker(String) method of the SwitchYardTestCase class (or one of its extensions).  The String parameter supplied to the newInvoker method can be just the target Service name (e.g. "OrderService"), or the target Service and target Operation names, separated by a dot/period chartacter (e.g. "OrderService.createOrder").  The operation name can also be explicitly specified via the Invoker.operation(String) method.

 

The Invoker class provides a few basic, but very useful, services to your unit test methods.  The main thing it does however is that it hides much of the complexity of creating the SwitchYard Exchange instance, required for sending messages to a service operation i.e. invoking a service operation.

 

The basic usage of the Invoker is very simple.  You just create the Invoker instance and then call one of the "send" methods to send a message payload to the target service operation e.g.

 

// Create the Invoker instance...
Invoker invoker = newInvoker("SimpleService.sayHello");

// Send a message payload to service (and wait for a response)...
Message response = invoker.sendInOut("Hello SimpleService!!");

// Make assertions on the response message...

 

For more control however, you can make additional configurations on the Invoker instance before calling the send method e.g.

 

// Create an Invoker with a longer asyn response timeout + a non-default
// ExchangeContract instance...
Invoker invoker = newInvoker("SimpleService.sayHello").
                        timeout(20000).
                        contract(specialExchangeContract);

 

InvocationFaultException

The sendInOut() method of the Invoker class declares InvocationFaultException as an exception type.  This exception will be thrown if the Exchange is in fault when the response (OUT message) is received.  Test methods can catch this exception, check the fault message etc and decide to fail the test, or not.

 

Arquillian

The goal with Arquiilian testing in SwitchYard is to provide a method with which SwitchYard services may be tested within the container.      Due to a number of issues regarding the SwitchYard AS6 deployer integration, this is not quite functional at the moment.

 

The current state of the Arquillian work is as follows : SwitchYard applications can be deployed out to a remote AS6 server and tested using Arquillian's client run mode.       Once the deployer issues are fixed, SwitchYard applications should be able to deployed to both embedded and remote servers and run in either container or client mode.

 

To try out the current state :

 

git clone https://github.com/cunningt/quickstarts
git pull origin newarq_m1
cd arquillian

 

<start an AS6 deployment with the SwitchYard deployer and both soap and bean components deployed>

 

mvn -Pjbossas-remote-6 clean install

 

Future work in this area also is planned around also deploying the SwitchYard prerequisites (the SwitchYard deployer, soap and bean components) through Arquillian, and using the new maven resolution functionality in the next version of Arquillian.