This two part series will focus on the creation and deployment of soapUI mock services in an enterprise environment. Part 1 deals primarily with mock service creation, configuration, and scripting. In Part 2, we'll look at exporting the mock service as a web application, deployment to a container, and performance considerations.

A Common Problem?

On a recent client engagement, our team, developing a custom middleware solution, faced an issue in which our development schedule paralleled and in some cases preceded that of other, interfacing parties involved in the project. Though we had a near-final contract (in WSDL form) for our back-end web service calls, we would not have an environment with both middleware and back-end solutions deployed and testable until well into the timeframe alotted for system test. We needed a solution that would allow our team to thoroughly test our middleware's back-end service calls before the actual back-end services were available.

I have found this to be a common and recurring problem in the development and integration of service-oriented solutions - both in the enterprise and strictly software engineering domains. Unfortunately, the hand-coded creation of web service stubs tends to be the solution of greatest prevalence. Our team needed a solution that was stable, scalable, and - most importantly - had a low level of effort for stub creation and deployment. After all, like most projects, we needed as much time as possible for the actual development and testing of our own solution. We couldn't afford to get bogged down coding faux versions of the very systems that we'd be interfacing with.

After a bit of research, we decided to use the oft-preferred tool for web service testing: Eviware's soapUI [http://www.soapui.org/]. I'd venture a guess that most use soapUI as a test tool for the consumption of existing services, given its suite of test-related features. However, the application also provides an easy way to stub out web service endpoints. And soapUI not only quickly hashes out a mock web service from an existing interface document (WSDL or WADL); it also encourages custom Groovy scripting for dynamic responses and includes the option to export the mock service as a WAR for deployment to an application server. As you'll see in the second part of this series, the deployment process is not without its problems, but we'll focus on mock service creation and scripting for a hypothetical client in the remainder of this post.

Our Hypothetical Project

Let's pretend our local library has decided to make its book repository accessible via a web service endpoint. They have an internal team that's going to expose simple, atomic operations on the repository, but they've hired us to aggregate those operations into a functional checkout service for use by the library's web application. For the purposes of this article, we'll leave the client-facing interface abstract.

The library has fallen behind on development of their services, but has provided a WSDL for us to work with in the meantime. We've coded our checkout service with calls to lookupMediaName, getCopiesAvailable, and reserveMedia based on the provided WSDL and are now ready to test. So... how do we go about executing our test cases if the back-end system isn't available? We don't want our test team sitting on their hands until the library's team is finished, and we also don't want to release these same resources temporarily, only to scramble for them when the system is ready for testing. Here's where soapUI comes in!

soapUI Mocks

To further simplify this example, we'll focus on only a single operation - let's assume that getCopiesAvailable and reserveMedia are ready to go, but the library has yet to implement lookupMediaName. The schema definition for lookupMediaName looks like (You'll need the full WSDL for the following soapUI exercise. Go ahead and pull it down from the end of the article.):

 
<> name="LookupMediaNameRq">
 <>>
 <>>
 <> name="MediaName" type="xs:string"/>
 
 
 <> name="MediaType" minOccurs="0">
 <>>
 <> base="xs:integer">
 <> value="3"/>
 <> value="0"/>
 >
 >
 >
 <> name="TransactionId" type="xs:integer"/>
 >
 >
>
<> name="LookupMediaNameRs">
 <>>
 <>>
 <> name="TransactionId" type="xs:integer"/>
 <> name="Result">
 <>>
 <> base="xs:string">
 <> value="SUCCESS"/>
 <> value="FAILURE"/>
 >
 >
 >
 <> name="MediaIdentifier" type="xs:string" minOccurs="0"/>
 >
 >
>

Before we get started, our system testers have requested that our mock lookupMediaName operation be able to mimic the following scenarios:

  • A TransactionId mismatch (i.e. request.TransactionId != response.TransactionId). Note that valid responses should have a Transaction Id matching that of the request.
  • A failure response
  • A success response
  • An empty response

The testers want to see how our middleware solution handles the situations listed above. Let's jump into soapUI and see what we can do. Note that the soapUI project and WSDL I've used here are attached at the end of this post.

1. Start by opening up soapUI and creating a new project (File->New soapUI Project). Point to the library WSDL in the 'Initial WSDL/WADL' entry box, and be sure to click the checkbox to 'Create a Web Service Simulation of the imported WSDL'. (Note that, even though it's called 'soap'UI, the tool includes support for RESTful/WADL-defined web services as well!)

2. You should see a new project created, with a new MockService instance. If you drill down a level, you'll see all the operations provided by this mock service. In our case, our WSDL only defined the lookupMediaName operation, so that's all we see. A WSDL with more operations will, obviously, result in more mock service operations. If you drill even further down, you should see a sample response, descriptively named 'Response 1'. soapUI will - conveniently - use the schema definition to draft an empty response for you. Double-click 'Response 1' to check it out.

3. Our testers listed four scenarios above, so we'll need four responses. Let's go ahead and rename 'Response 1' to something more descriptive - 'TransIdMismatchResponse'. Right-click the lookupMediaName operation and click 'New MockResponse' to create three more responses, naming them descriptively. We'll fill the responses with appropriate content later. You should have something that looks like:

4. So we've got our responses, but now we're faced with a couple of problems. The first concerns the testers - how can they control which response gets returned? The second involves the TransactionID field - how can we make sure we include the same value from the requests in our responses?

4.1 Let's tackle the first problem. When executing a given test script, we'll probably want the ability to 'force' a certain response, so that we can be sure it matches up with expectations in the test case. Go ahead and double click the 'lookupMediaName' operation under your project and take a look at the Dispatch drop-down:

As you can see, you have a few options beyond the default 'SEQUENCE', which will just iterate through each of your responses for each successive request. We're going to use the 'SCRIPT' option in our example, which lets us build a Groovy or JavaScript scriptlet to dynamically determine the response. More details on dispatch types can be found on the soapUI website - http://www.soapui.org/Service-Mocking/simulating-complex-behaviour.html.

Select the 'SCRIPT' option. We'll give the testers the ability to control responses based on the book name in the request. (In a real-world example, we'd obviously have the ability to use more complex logic in determining a response.) In the following script, we're using a Groovy utility called XmlSlurper to parse the request and extract the MediaName field, and choose the request based on this field. Add the below into your soapUI script window, and/or tweak it as you see fit! One thing that helps when you're dealing with a lot of test scenarios (and therefore a lot of responses) is to load your response mappings into a HashMap at server start-up, and then access the HashMap at the operation level to determine the response. This lets you skip the conditional blocks each time the mock service handles a request. We're going to keep it simple in this example, but if you're interested, you can double-click the service in the navigation window to add scripts for certain service events.

4.2 Our other problem is returning the same TransactionID value from the request in our response (at least, for three out of four of our response scenarios). Since we're already parsing the request XML in our dispatch script, it makes sense to pull the TransactionId field out at the same time. SoapUI lets us store this in a context associated with the request, for use at the response level. Add the following Groovy scripting to your operation / dispatch script:

import groovy.util.XmlSlurper
 
def parsedContent = new XmlSlurper().parseText(mockRequest.requestContent)
 
//dispatch based on request MediaName
def mediaName = parsedContent.Body.lookupMediaName.LookupMediaNameRq.MediaName.toString()
def responseToUse = "";
 
if (mediaName.equals("Catcher in the Rye")) {
 responseToUse = "SuccessResponse"
} else if (mediaName.equals("Of Mice and Men")) {
 responseToUse = "TransIdMismatchResponse"
} else if (mediaName.equals("Cloud Atlas")) {
 responseToUse = "FailureResponse"
} else if (mediaName.equals("A Canticle for Leibowitz")) {
 responseToUse = "EmptyResponse"
} else {
 
 //default to success response
 responseToUse = "SuccessResponse"
}
 
return responseToUse

So you should now have an operation/dispatch script that looks like:

5. Lastly, we need to fill out our responses. This is the easy part (at least for our simple example). We can use a custom syntax in our response to use the transactionID value from the request context. It's as easy as enclosing the context variable as follows ${transactionId}. Here are our responses:

Success
<> xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:lib="http://fauxlibrary.com/library-ops">
 <>/>
 <>>
 <>>
 <>>
 <>>${transactionId}>
 <>>SUCCESS>
 
 <>>1234>
 >
 >
 >
>
Failure
<> xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:lib="http://fauxlibrary.com/library-ops">
 <>/>
 <>>
 <>>
 <>>
 <>>${transactionId}>
 <>>FAILURE>
 
 <>>5678>
 >
 >
 >
> 
Transaction Id Mismatch
<> xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:lib="http://fauxlibrary.com/library-ops">
 <>/>
 <>>
 <>>
 <>>
 <>>9999>
 <>>SUCCESS>
 
 <>>9012>
 >
 >
 >
>

6. You can go ahead and start the service within the soapUI environment (double click the service name in the nav bar and hit the play button on the service window that pops up). Try and hit it with a request, either from within soapUI or with another tool / application! I'm running the 'success' scenario through a soapUI request in the image below.

Conclusion

SoapUI provides a way to create versatile mock services quickly and efficiently. Once you get the hang of things, it's easy to knock out a set of mock responses and corresponding dispatch logic in a matter of minutes. In my own experience, soapUI has provided a way to quickly turn out mocks for our system test team, and allows for quick and easy modifications & test case additions. In the next post, we'll export the project as a WAR file, examine some difficulties and solutions in deploying the project to an application server, and look into the capabilities of our mock services in performance/load testing.

Also, note that the steps above don't hold a candle to the detailed and comprehensive documentation on the soapUI website. My focus here has been to show users how to apply this powerful tool given an enterprise scenario and to use some nifty Groovy scripting to handle dispatching, request dependencies, etc. Such information seemed scattered or lacking in my own research and project experiences.

References