Archive

Posts Tagged ‘soapui’

soapUI Tip: Options for Refreshing a WSDL Definition

December 29, 2010 1 comment

Here’s a quick tip for soapUI users that I have been stumbling over recently.  soapUI allows you to refresh an already defined service definition from an updated WSDL file.  But, it’s easy to blow away the data that’s in your SOAP test steps if you chose the wrong options.

First, here’s the specific task I’m talking about.  You have an existing soapUI workspace that has interface definitions already imported and you have at least one test suite using that interface.  Now you’ve made a change to the WSDL and you need to refresh your interface definition in soapUI and update the SOAP test steps in your test suite.  Clearly, you want to update the SOAP requests to match the new WSDL without losing the test data that already exists in the test steps.  You reload a WSDL definition by right-clicking on an interface definition in soapUI as shown below.

Here’s a rundown of the effect of some of the “Update Definition” parameter configurations.  I haven’t gone through every permutation of the parameters, just the ones that seem most useful.  I’ve portrayed the configurations in terms of actions you’re likely to want to take after changing your WSDL.

  • You added a new operation to the WSDL and you want to add default requests for it.

  • You made a change to an existing operation in your WSDL and you want to regenerate existing requests using the new schema without creating optional elements.  This configuration will cause you to lose the data in your existing requests.

  • You made a change to an existing operation in your WSDL and you want to regenerate existing requests using the new schema and create optional elements.  This configuration will cause you to lose the data in your existing requests, unless the elements are optional.

  • You made a change to an existing operation in your WSDL and you want to regenerate existing requests using the new schema and create optional elements.  This configuration will keep the existing data in tact.

  • You made a change to an existing operation in your WSDL and you want to regenerate existing requests and test steps using the new schema without creating optional elements.  This configuration will keep the existing data in tact but will remove optional elements from the existing requests.

  • You made a change to an existing operation in your WSDL and you want to regenerate existing requests and test steps using the new schema and maintain optional elements.  This configuration will keep the existing data and optional elements in tact.

  • The last configuration is the safest bet for most refreshes.  It combines all of the above. That means that it picks up all WSDL changes and incorporates them into both default requests and your SOAP test steps.  None of your existing data will be overwritten.  It also opens up a window that lists exactly which items have been modified.

I have not mentioned the “Keep SOAP Headers” and “Create Backups” parameters because I have not used them yet.

I suggest playing around with the “Update Definition” feature a little before using it.  soapUI is a powerful tool, so it assumes you know what you want.  It accomplishes that by exposing panels with lots of parameters on them, like the “Update Definiton” panel.  If you get yourself into a bind, remember that you can just reload the project you’re working on by right-clicking on the project name and choosing “Reload Project”.  This option will reload the project into the workspace without saving the changes you just made.

How to Enable MTOM Support for JAX-WS Web Services Running on WebSphere Application Server

August 6, 2010 Leave a comment

I’m going to keep this post short today.  This is something I ran across today and it was rather irritating that I couldn’t find any good documentation on the subject. This is a highly specific problem but it might help a few of you out there.

Here’s the scenario.  I’m working on building a web service using JAX-WS 2.1 that is being deployed to WebSphere Application Server (WAS) 7.0.  I’m using Rational Application Developer (RAD) version 7.5.5.1 as my IDE. It’s a very simple web service that has to return moderate sized binary data chunks in the SOAP response (PDF files).  My team have decided to use the Message Transmission Optimization Mechanism (MTOM) as the method for attaching the bytes of the PDF files.  This is a relatively painless process if you have all the information you need.  However, the IBM WAS 7 InfoCenter has an incomplete description of how to enable MTOM on a web service.  IBM’s documentation tells you how to annotate your web service properly, but it doesn’t tell you that you also need to make a change to the IBM-specific webservices.xml file.  webservices.xml can be found in your Web Content\WEB-INF folder in your web application.

The change you have to make to webservices.xml is simple.  You just have to find the <webservice-description> tag for the web service on which you are enabling MTOM then change the value of the <enable-mtom> tag from false to true.  An example (a fragment of the webservices.xml file) of what this should look like is given below.

<webservice-description>
   <webservice-description-name>MyWebService</webservice-description-name>
   <port-component>
     <port-component-name>MyWebService</port-component-name>
     <wsdl-service xmlns:pfx="http://www.comapny.com/MyWebService/">
       pfx:DocumentService</wsdl-service>
     <wsdl-port xmlns:pfx="http://www.company.com/MyWebService/">
       pfx:DocumentServiceSOAP</wsdl-port>
     <enable-mtom>true</enable-mtom>
     <service-endpoint-interface>com.comapny.MyWebService</service-endpoint-interface>
     <service-impl-bean>
       <servlet-link>com.comapny.MyWebServiceSOAPImpl</servlet-link>
     </service-impl-bean>
   </port-component>
 </webservice-description>

Once your web service has been properly annotated and you make the above change to webservices.xml your web service will be setup to support MTOM.

Summary

To summarize, you have to follow two steps to get MTOM support in your JAX-WS web service:

  1. Follow IBM’s documentation on annotating your web services implementation classes properly for MTOM support.
  2. Set the <enable-mtom> tag to true in the webservices.xml file.

One more note is that the problem of IBM’s incomplete documentation is exasperated by the fact that their “Generate Java bean skeleton” wizard also neglects to update the webservices.xml file properly.  Even if you check the “Enable MTOM Support” check box on the “WebSphere JAX-WS Top Down Web Service Configuration” screen the webservices.xml file will remain unchanged after the wizard completes.  So whether you are using the wizard to create your web service code or doing it manually, you will have to update the webservices.xml afterward to fully enable MTOM support.

Explaining the Confusion

The webservices.xml file is actually completely optional — at least according to This WAS 7 InfoCenter page. Supposedly you can remove the webservices.xml file from your application and the annotations will be enough to enable MTOM support and you won’t have to go through any extra, manual steps.  If I sound unsure it’s because I am.  I tried removing the webservices.xml file from my web service and, after a re-deploy to the server, it was no longer accessible (received this error: “Error 404: SRVE0190E: File not found: /MyWebService”).  Once I restored the webservices.xml file and re-deployed I could reach the web service.

What I can verify is that the file is used on the server side to override any annotations that are found in the web service code.  This explains why MTOM doesn’t work unless you have <enable-mtom> set to true in webservices.xml.  Unfortunately, this is also probably why the file is not kept in sync when generating the code although I have no proof to back up that statement.  Please comment if you have a better or more correct explanation!

References

It seems that none of the official IBM references really catch this problem (otherwise I would not be writing this post :) ).  As mentioned earlier in this post, the IBM WAS 7 InfoCenter has some basic directions on enabling MTOM support that are incomplete.  Two other references of high quality, but also incomplete, with respect to MTOM support, are the Redbooks IBM WebSphere Application Server V7.0 Web Services Guide and Rational Application Developer V7.5 Programming Guide.  The Redbooks offer different levels of detail about MTOM support, so it’s worth your time to research MTOM in both books.

Configure HTTP Basic Auth for soapUI Test Suties.

August 5, 2010 4 comments

Since soapUI is a powerful tool, it frequently offers more than one way to do things.  Setting up HTTP Basic Authentication is one of these things.  If you’re dealing with a SOAP based web service that has this kind of security setup, this article will show you how to best configure your soapUI tests to supply the basic authentication credentials.  The username and password supplied for HTTP Basic Authentication is ultimately an HTTP header field.  As such, each SOAP test request in soapUI can be configured with a HTTP Basic Authentication username and password.  When the test request is run an “Authorization” header is added to the HTTP envelope that contains the SOAP request.  Here’s an example:

Authorization: Basic QRJ3aXphblByb2ZpbGU6VGVzdCCmMs==

There are at least three ways in soapUI to setup HTTP Basic Authentication:

  1. on each SOAP test request (in a test case or in sample request)
  2. through the “Interface Viewer”
  3. with a Groovy setup script for a test suite.

Setting up HTTP Basic Authentication for A Test Request

This is an easy, quick way to set the username and password for a few requests, but not a good solution for a test suite.  When you use this method each individual SOAP test request must have the username and password set for the request to work properly.  With a SOAP test request open, you can change the username and password for that request by clicking the button labeled “Aut” underneath the request pane, as shown below.  Just enter the username and password in the fields.  The next time you run the SOAP request the “Authorization” header will be added to the HTTP envelope.

Setting up HTTP Basic Authentication through the Interface Viewer

If you know that many SOAP test requests will need to share the same HTTP Basic Authentication credentials, you’ll want to just set them one time.  You can do this through a soapUI tool called the Interface Viewer.  To open the Interface Viewer, right-click on a WSDL operation in the project explorer tree on the left-hand side of the soapUI interface and choose “Show Interface Viewer”.  This will open a screen with four tabs: Overview, Service Endpoints, WSDL Content, and WS-I Compliance.  The HTTP Basic Authentication credentials are set through the “Service Endpoints” tab.  For each endpoint in the list you can specify what username and password to use.  Once specified, all of the test requests on the WSDL operation (the one you selected to open the Interface Viewer) using the specific endpoint will automatically use the username and password you entered.  An example of using the Interface Viewer is shown below.

Setting up HTTP Basic Authentication with a Groovy Test Suite Setup Script

Another fairly effective way to do this setup for all the SOAP test requests in a test suite is with a Groovy setup script.  Using the Interface Viewer is probably a more convenient way to do the setup than the Groovy script, but if you need some more control then you might have to use the script.  Below is a sample Groovy script that you could copy and paste into the “Setup Script” text box for one of your test suites.  The script relies on the existence of  two properties which must be defined in the test suite: basicAuthUser and basicAuthPass.  These properties should contain, respectively, the username and password to be used in the HTTP Basic Authentication header for each SOAP test request in the test suite.

import com.eviware.soapui.impl.wsdl.teststeps.*

for( testCase in testSuite.getTestCaseList() ) {
   log.info("Setting HTTP basic auth for all WSDL test requests in test case ["+
             testCase.getLabel()+"]")
  for( testStep in testCase.getTestStepList() ) {
    if( testStep instanceof WsdlTestRequestStep ) {
      testStep.getTestRequest()
              .setUsername(testSuite
                           .getPropertyValue("basicAuthUser"))
      testStep.getTestRequest()
              .setPassword(testSuite
                           .getPropertyValue("basicAuthPass"))
    }
  }
}

The script above uses the soapUI Java API to access the necessary pieces of the test suite.  It first loops over all of the test cases in the test suite.  For each test case, the script loops over each test step therein.  If the test step is a WsdlTestRequestStep, which is a SOAP test request, then the username and password are set.  This script will run just before the test cases run when the entire test suite is executed.

Some Thoughts on Integrating SoapUI Functional Tests with Your Build

June 23, 2010 6 comments

The development team I’m a part of at Ohio Mutual Insurance Group is about to develop our own web services for the first time and I want to make sure we test them properly. So, for about two months now I have been experimenting with using SoapUI to aid in developing our services.  One very important aspect of my experiment is to determine how difficult it is to run SoapUI functional tests from a Hudson CI job. In this blog are my rough thoughts on how well SoapUI functional tests integrate with the build process we use on Hudson.

Functional testing is not all SoapUI does, but it is one outstanding feature that I’m focusing on for now. Even though SoapUI has a solid interface for running functional tests, it doesn’t make any sense to have compilation, unit tests, and deployment automated but not functional tests.  It appears that the SoapUI developers feel the same way and have provided some help in this area. There are two ways to run SoapUI functional tests automatically: integrate with JUnit or use the SoapUI “testrunner” shell script.   Unfortunately, the official documentation on both is sparse (see the hyperlinks in the previous sentence)  and not helpful beyond a bare minimum of support.

Note: All mention of SoapUI in this entry is related to version 3.5.1.

Integrating with JUnit

The documentation for how to integrate with JUnit is awful.  It barely provides the necessary information for using JUnit and only offers part of the story.  If you really want to know how to run your SoapUI tests from JUnit you’re mostly stuck with using the SoapUI JavaDocs and your own experimentation (Intellisense is your friend here).  However, the one advantage that this approach has over using the testrunner script is that you can have more control over how and when tests are executed. If you need that control but want to automate the process of running the test cases, this is the way to do it. But, if you just need to automate the test case runs without control, the command line test runner is preferable. Here is some help with the JUnit method.

To run SoapUI tests from JUnit tests you have to use the SoapUI API.  This means that the SoapUI libraries need to be in your Classpath.  The main archive needed is the bin\soapui-3.5.1.jar file.  If they’re not already in your Classpath, you may also need some of the JARs in the lib directory.  At a minimum you will need the xmlpublic-2.4.0.jar because it contains the XMLException class that is thrown by some of the classes in the SoapUI API.

When you’ve got your Classpath setup you can use the SoapUI API in your JUnit tests.  There are several ways to run SoapUI functional tests with the SoapUI API.  You can just run all the test cases in all the test suites in a SoapUI project without control over the order (you choose whether to run them synchronously or asynchronously), run a whole test suite, or run individual test cases within a test suite.  For the second and third options, you can either blindly iterate over test suites and test cases or you can run test suites or test cases by name.  Which way you run the tests is based on how much control you need over the order of test execution.  When running a test suite you have control over whether the test cases in the suite are run synchronously or asynchronously.  The options that you have available reflect what you can do in SoapUI’s user interface.  The problem is digging through the JavaDocs to find out which methods on what objects to call.

Here is an example of a JUnit test that runs all the test cases in a SoapUI project in two different ways.  The lessControl method just runs every test case in the project in the simplest way whereas the fullControl method iterates over the test suites and the test cases in the project.

package com.omig.soapUISamples;

import java.util.List;
import org.junit.Test;
import com.eviware.soapui.impl.wsdl.WsdlProject;
import com.eviware.soapui.model.support.PropertiesMap;
import com.eviware.soapui.model.testsuite.TestCase;
import com.eviware.soapui.model.testsuite.TestRunner;
import com.eviware.soapui.model.testsuite.TestSuite;
import com.eviware.soapui.model.testsuite.TestRunner.Status;
import com.eviware.soapui.tools.SoapUITestCaseRunner;
import static org.junit.Assert.*;

public class SoapUITest {

@Test
public void lessControl() throws Exception {
SoapUITestCaseRunner runner = new SoapUITestCaseRunner();
runner.setProjectFile(“SoapUIWorkspace/Sample-soapui-project.xml”);
runner.setPrintReport(true);  //Outputs a small table to stdout of test results.
runner.run();
}

@Test
public void fullControl() throws Exception {
WsdlProject project = new WsdlProject(“SoapUIWorkspace/Sample-soapui-project.xml”);
List<TestSuite> testSuites = project.getTestSuiteList();
for( TestSuite suite : testSuites ) {
List<TestCase> testCases = suite.getTestCaseList();
for( TestCase testCase : testCases ) {
System.out.println(“Running SoapUI test [" + testCase.getName() + "]“);
TestRunner runner2 = testCase.run(new PropertiesMap(), false);
assertEquals(Status.FINISHED, runner2.getStatus());
}
}
}
}

With the code above you’ve got a hint at how run SoapUI functional tests from a JUnit test.  To actually make this automatic you’ve got (at least) one more step.  In my situation we use Ant to script our software builds.  We then use Hudson to schedule the builds and make it all run automatically.  There are a lot of other ways you could do this but I’ll only show the Ant way here.  Any build tool that has support for JUnit will suffice.

Below is an example of an Ant task that runs the JUnit tests that are executing the SoapUI tests.  The JUnit output is being generated in XML format and sent to a folder named soapui-test-reports.

<path id="classpath">
    <!-- The path to the lib folder in the SoapUI installation.-->
    <fileset dir="${env.SOAPUI.LIB}"/>
    <!-- The path to the bin folder in the SoapUI installation.-->
    <fileset dir="${env.SOAPUI.BIN}"/>
</path>

<path id="soapui-workspace">
    <fileset dir="SoapUIWorkspace">
      <include name="**/*.xml"/>
    </fileset>
</path>

<target name="soapui-tests" depends="compile">
    <mkdir dir="../soapui-test-reports" />
    <junit printsummary="withOutAndErr"
           showoutput="true"
           haltonerror="on"
           haltonfailure="on"
           filtertrace="off"
           fork="no"
           forkmode="once">
      <classpath refid="classpath" />
      <classpath refid="soapui-workspace" />
      <formatter type="xml" />
      <batchtest todir="../soapui-test-reports">
        <fileset dir="tests">
                <include name="**/*SoapUI*.java"/>
        </fileset>
      </batchtest>
    </junit>
</target>

Testrunner Script

The documentation for the testrunner script is much clearer than for integrating with JUnit.  Integrating the testrunner.bat file with your build process is simple and straight-forward. An example of an Ant task to do this is shown below.  See SoapUI’s documentation for an explanation of the command line switches.

<target name="soapui-tests-cmdline" depends="compile">
        <exec executable="${env.SOAPUI.BIN}/testrunner.bat"
                  failonerror="yes"
                  failifexecutionfails="yes">
                <arg value="-rjaf"/>
                <arg path="../soapui-test-reports"/>
                <arg path="SoapUIWorkspace/Insured-Access-soapui-project.xml"/>
        </exec>
</target>

Which Method Is Best?

In my experience so far the command line testrunner tool is the better method for several reasons:

  1. There’s less work because you do not have to write a JUnit test suite/case to run the SoapUI tests.
  2. It creates a less fragile environment because writing a JUnit test to run the SoapUI tests makes it very difficult not to hard code the path to the SoapUI project file. You don’t have to worry about this with the command line because the input to script is parametrized.
  3. The command line test runner can output “correct” JUnit output. The JUnit reports generated by the command line test runner split results by test suite then test case. This is ideal when the results are viewed graphically because you get a full count of actual test cases run and you can drill-down to the individual test cases to see its run status*.
  4. To integrate with JUnit you have to use the SoapUI API, which is not documented well. There are Javadocs, but actual documentation is sparse in them.

* As far as I can tell it is difficult or impossible to do this by integrating with JUnit manually. To do so you would have to somehow generate one JUnit test for each test case in all the test suites. The SoapUI API allows you to easily iterate over the test suites and test cases, but there is no way in Java to dynamically generate methods for each test case.

Follow

Get every new post delivered to your Inbox.

Join 126 other followers