Showing posts with label soapUI. Show all posts
Showing posts with label soapUI. Show all posts

Saturday, October 29, 2011

Back to soapUI: testing web services and Java RMI services

I already covered soapUI in one of my previous blog posts. As I still use this tool quite often and extremely excited about it, I would like to share more testing scenarios we as a developers can use on day-by-day basis. The ones for today's post would be: testing web services and Java RMI services.

So first thing first: let's assume we are developing application which exposes web services and our goal is to have some integration testing in place. We don't want to hard-code SOAP requests and responses, we want to leverage Groovy to code real test cases. Thanks to soapUI, it's so easy to do by using Groovy test steps. Let me omit the routine and focus on bare bones details. I created a simple test project in soapUI with this structure:

The interesting part is here: Call web service Groovy step. Before we move on, let's copy several JAR files to <soapUI home>\bin\ext folder: Then we need to restart soapUI. Now we are ready to fill in the Groovy step with some code. Thanks to GroovyWS, calling web service from Groovy is very easy:

import groovyx.net.ws.WSClient

def properties = testRunner.testCase.getTestStepByName( "Properties" )
def service = new WSClient( properties.getPropertyValue( "url" ), this.class.classLoader )
service.initialize()

def token = service.login(
 properties.getPropertyValue( "username" ),
 properties.getPropertyValue( "password" )
)

assert token != null, "Login is not successful"
Properties step just contains username, password and url configuration:
And that's it! Now we can call additional web service methods and easily run this test case as load test: just to verify how web service behaves under heavy load. I usually do it overnight to see application heap, GC and whatnot. Cool.

Second use case: testing Java RMI services. This one requires a bit more work to be done. First of all, you need soapUI to be run using RMISecurityManager. Let's do this.

  1. Create file soapui.policy with content below and store it in <soapUI home>\bin:
    grant {
        permission java.security.AllPermission;
    };
    
  2. Change soapUI command line (<soapUI home>\bin\soapui.bat). Find the line set JAVA_OPTS=... and append to it:
    -Djava.security.policy=soapui.policy -Djava.security.manager=java.rmi.RMISecurityManager
    
    So you will have something like this: set JAVA_OPTS=-Xms128m -Xmx1024m -Dsoapui.properties=soapui.properties "-Dsoapui.home=%SOAPUI_HOME%\" -Djava.security.policy=soapui.policy -Djava.security.manager=java.rmi.RMISecurityManager
To run a bit ahead, we need to copy several JAR files to <soapUI home>\bin\ext folder: Now we a good and just need to restart soapUI. The sample project structure is very similar to what we did before:

Respective Groovy test step is built using Spring Framework which significantly simplifies creating RMI stubs and clients by getting rid of the boilerplate code.
import org.springframework.remoting.rmi.RmiProxyFactoryBean
import com.example.RmiServiceInterface

def properties = testRunner.testCase.getTestStepByName( "Properties" )
def invoker = new RmiProxyFactoryBean( 
 serviceUrl: properties.getPropertyValue( "url" ), 
 serviceInterface: com.example.RmiServiceInterface 
)
invoker.afterPropertiesSet()

def service = invoker.object
def token = service.login(
 properties.getPropertyValue( "username" ),
 properties.getPropertyValue( "password" )
)

assert token != null, "Login is not successful"
Now our service is ready for more serious testing. As with web services scenario Properties step just contains username, password and url (RMI) configuration:
I personally found soapUI to be very helpful tool in my developer toolbox and I definitely recommend using it.

Sunday, June 6, 2010

Testing BlazeDS remote objects with soapUI

Testing never was an easy thing. I am following TDD approach for at least last 5-6 years and really excited about it. But for me, TDD is not only unit testing. It is whole set of testing techniques I find appropriate for particular project (unit tests, integration tests, performance tests, ...). Recently I discovered excellent tool - soapUI. It has a bunch of useful features but the one I would like to cover today is testing BlazeDS services using AMF protocol.

Before we start with code snippets, let's copy BlazeDS libraries to bin/ext folder of soapUI installation:
- commons-codec-1.3.jar
- commons-httpclient-3.0.1.jar
- commons-logging.jar
- flex-messaging-common.jar
- flex-messaging-core.jar
- flex-messaging-opt.jar
- flex-messaging-proxy.jar
- flex-messaging-remoting.jar

Among other very cool features, soapUI supports Groovy as a scripting language which is just awesome. So all my examples will be in Groovy. Let's start with necessary part: creating connection and aliasing services.
import flex.messaging.io.amf.ASObject;
import flex.messaging.io.amf.client.AMFConnection;
import flex.messaging.messages.CommandMessage;
import flex.messaging.util.Base64.Encoder;
import flex.messaging.messages.Message;
import flex.messaging.io.amf.ASObject;

def clientId = "soapUI." +  UUID.randomUUID().toString();
def amfConnection = new AMFConnection();
amfConnection.instantiateTypes = false

amfConnection.connect(  "http://localhost:8080/server/messagebroker/amf" );   
amfConnection.addAmfHeader( Message.FLEX_CLIENT_ID_HEADER, clientId );

// Create remote object aliases
amfConnection.registerAlias( "testService", "com.example.remoteobjects.TestFacade" );
Having connection established, we are ready to call service methods of any aliased remote objects. Here is a code snippet to call service method foo() which has no parameters.
// Calling service method without arguments
def result = amfConnection.call( "testService.foo" );
And here is a code snippet to call service method foo() which accepts one parameter of type Person.
// Calling service method with object as argument
def person = new ASObject( "com.example.Person" );
person["name"]= "John Smith" ;

result = amfConnection.call( "testService.foo", person );
There's one issue which I've omitted for a moment. If you have security enabled for channels, you must proceed with authentication before calling any services. It's quite simple to do:
def credentials = encodeToBase64( username ) + ":" + encodeToBase64( password );

CommandMessage c = new CommandMessage();
c.setHeader( Message.FLEX_CLIENT_ID_HEADER, clientId );
c.setOperation( CommandMessage.LOGIN_OPERATION );
c.setDestination( "auth" );
c.setBody( encodeToBase64( credentials ) );      
amfConnection.call( null, c );

def encodeToBase64( final byte[] bytes ) {
    Encoder encoder = new Encoder( bytes.length );
    encoder.encode( bytes );
    return encoder.drain();     
}
When we are done, let's be a good citizens and close connection:
amfConnection.close();
Again, if security for channels is enabled, do logout before closing connection:
CommandMessage c = new CommandMessage();  
c.setHeader( Message.FLEX_CLIENT_ID_HEADER, clientId );
c.setOperation( CommandMessage.LOGOUT_OPERATION );
c.setDestination( "auth" );   
amfConnection.call( null, c );
Having such a script, soapUI allows you to create load test based on it. It also support quite complicated scenarios with many scripts involved and parameters passed from one to another. There is very good blog which contains tons of very useful information how to use soapUI for different kind of testing.