Menu

Home

Jacek Obarymski

SOAP/REST Mock Service - User's Guide

Overview

SOAP/REST Mock Service is a simple configurable framework for mocking out SOAP or RESTful (or "REST-like") webservices. It's main goal is to support automated integration testing of applications that integrate with 3rd party webservices. Functionality and usage scenarios of the mock service are in a way analogous to unit testing mocking tools (like Mockito or EasyMock). Once properly configured, SOAP/REST Mock Service exposes wbeservice mocks that can be called from application code and controlled via REST interface from integration tests code, enabling to set mock responses and verify recorded requests.

How does it work?

Typical integration testing scenario

Typical integration test involving usage of the SOAP/REST Mock Service is in a way analogous to a unit test utilizing tools like Mockito or EasyMock. Let's assume we have a system under test which calls external webservice(s). Typical testing scenario would involve:

  1. Initialisation of mock service
  2. Setting up a mocked webservice response or a series consecutive responses on the mock service.
  3. Executing the routine under test which calls external webservices (here webservice mocks).
  4. Checking webservice request(s) that tested application sent to the mock service
  5. Checking state of the tested application e.g. response of the tested routine

Configuring mocked webservice endpoints.

To add new ws endpoint add a ws-mock.properties file to the classpath visible to the mock service application. Edit the file and add a webservice definition:

Property Description
SERVICE[i].NAME name of webservice
SERVICE[i].TYPE SOAP or REST
SERVICE[i].WSDL name of wsdl file, relevant only to SOAP webservices; the wsdl file should be placed in the classpath visible to the mock service application
SERVICE[i].OPERATION[j].INPUT_MESSAGE (optional) root element of request message; relevant only to SOAP webservices; skip this if WSDL is provided, this information will be read from the WSDL file
SERVICE[i].OPERATION[j].HTTP_METHOD http method of mocked REST service; relevant only to REST webservices; available methods: GET, POST, PUT, DELETE
SERVICE[i].OPERATION[j].DEFAULT_RESPONSE name of file containing default response; the file should be placed on classpath; skip this if WSDL is provided, the default response will be generated from the WSDL file
SERVICE[i].OPERATION[j].DEFAULT_RESPONSE_CODE (optional, only for REST, default: 200) HTTP code of default response
SERVICE[i].OPERATION[j].DEFAULT_RESPONSE_CONTENT_TYPE (optional, only for REST, default: text/xml ) content type of default response, e.g. application/json, text/xml

You can add multiple webservice endpoint definitions. Just add next SERVICE[i] definition with incremented [i] index.

Within particular SOAP WS endpoint you can define multiple operations and within REST service definition you can service different HTTP methods. Just add next OPERATION[j] definition incrementing [j] index

Examples:

Here're two ways of defining a mock of WebserviceX's currency convertor SOAP service, which is publicly available under.
http://www.webservicex.net/CurrencyConvertor.asmx?WSDL
Add the following lines to the ws-mock.properties file which should available in classpath.

Either provide a WSDL file (works for WSDL ver. 1.1 only) of the mocked service:

SERVICE[0].NAME=webservicex-rate-convertor
SERVICE[0].TYPE=SOAP
SERVICE[0].WSDL=webservicex-rate-convertor.wsdl

or provide input message and a file containing default response:

SERVICE[0].NAME=webservicex-rate-convertor
SERVICE[0].TYPE=SOAP
SERVICE[0].OPERATION[0].INPUT_MESSAGE=ConversionRate
SERVICE[0].OPERATION[0].DEFAULT_RESPONSE=webservicex-rate-convertor-default-response.xml

API

Mock service can be invoked and controlled by it's RESTful API.
Parameter names starting with SERVICE[i] exchange with respective parameter values defined in the ws-mock.properties file.
Please check the API reference for a detailed reference to the options provided by SOAP/REST Mock Service

List of available service mocks

You can check what service mocks have been defined under the following URL

http://server:port/{APP_CONTEXT}/services
Address of mocked endpoint

A mocked webservice endpoint is available under the following URL:

http://server:port/{APP_CONTEXT}/services/{SERVICE[i].TYPE}/{SERVICE[i].NAME}/endpoint
Initializing a webservice mock

POST to this URL will initialize mock service endpoint and erase recorded requests:

http://server:port/{APP_CONTEXT}/services/{SERVICE[i].TYPE}/{SERVICE[i].NAME}/operations/{SERVICE[i].OPERATION[j].INPUT_MESSAGE}/init
Setting mock responses

POST to this URL, with request body containing any xml/json string will set the mock’s response to this string (only for the duration of one request).

http://server:port/{APP_CONTEXT}/services/{SERVICE[i].TYPE}/{SERVICE[i].NAME}/operations/{SERVICE[i].OPERATION[j].INPUT_MESSAGE}/responses - adding custom response; serial POSTs to this URL will set consecutive responses

PUT to this URL will set response to n'th consecutive request

http://server:port/{APP_CONTEXT}/services/{SERVICE[i].TYPE}/{SERVICE[i].NAME}/operations/{SERVICE[i].OPERATION[j].INPUT_MESSAGE}/responses/{n} - setting n'th response
Checking what requests to 3rd party had been rececorded

GET on this URL will cause the mock to display recorded requests:

http://server:port/{APP_CONTEXT}/services/{SERVICE[i].TYPE}/{SERVICE[i].NAME}/operations/{SERVICE[i].OPERATION[j].INPUT_MESSAGE}/recorded-requests

Note: For REST service mock use SERVICE[i].OPERATION[j].HTTP_METHOD instead of SERVICE[i].OPERATION[j].INPUT_MESSAGE for constructing links

Usage

It's a maven project. It has been released to central maven repository. You can configure your application's maven copy it from the repo and run in during integration-test phase.

Automated tests during test phase of maven build.

You can use jetty-mave-plugin and run it in an embedded jetty container during maven integration-test phase, along with your application under test.
In order to do that copy the following configuration to your application's pom file:

First copy the artifact from maven central repository using maven-dependency-plugin.

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>2.4</version>
            <executions>
                <execution>
                    <id>copy-wars</id>
                    <phase>package</phase>
                    <goals>
                        <goal>copy</goal>
                    </goals>

                    <configuration>
                        <outputDirectory>${project.build.directory}/external-wars</outputDirectory>
                        <stripVersion>true</stripVersion>
                        <artifactItems>
                            <artifactItem>
                                <groupId>net.sf.jaceko</groupId>
                                <artifactId>soaprest-mock-service</artifactId>
                                <version>1.5.0</version>
                                <type>war</type>
                            </artifactItem>
                        </artifactItems>
                    </configuration>
                </execution>
            </executions>
        </plugin>

... and deploy it to jetty along with the tested application using jetty-maven-plugin

        <plugin>
            <groupId>org.mortbay.jetty</groupId>
            <artifactId>jetty-maven-plugin</artifactId>
            <version>8.1.5.v20120716</version>
            <configuration>
                <stopKey>STOP</stopKey>
                <stopPort>9992</stopPort>
                <scanIntervalSeconds>5</scanIntervalSeconds>
                <webAppConfig>
                    <contextPath>/currency-calculator</contextPath>
                </webAppConfig>
                <connectors>
                    <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
                        <port>8080</port>
                        <maxIdleTime>60000</maxIdleTime>
                    </connector>
                </connectors>

                <contextHandlers>
                    <contextHandler implementation="org.mortbay.jetty.plugin.JettyWebAppContext">
                        <contextPath>/mock</contextPath>
                        <war>${project.build.directory}/external-wars/soaprest-mock-service.war</war>
                        <extraClasspath>${basedir}/src/test/resources/soaprest-mock-resources</extraClasspath>
                    </contextHandler>
                </contextHandlers>
                <useTestClasspath>true</useTestClasspath>

            </configuration>

            <executions>
                <execution>
                    <id>start-jetty</id>
                    <phase>pre-integration-test</phase>
                    <goals>
                        <goal>stop</goal>
                        <goal>run</goal>
                    </goals>
                    <configuration>
                        <scanIntervalSeconds>0</scanIntervalSeconds>
                        <daemon>true</daemon>
                    </configuration>
                </execution>

                <execution>
                    <id>stop-jetty</id>
                    <phase>post-integration-test</phase>
                    <goals>
                        <goal>stop</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

Put the ws-mock.properties file in the /src/test/resources/soaprest-mock-resources folder of your application.

You can also start jetty server from your integration test code:
Have a look at integration tests in this project

Manual tests, load tests...

You can also use it outside of maven build process. Just deploy the mock service's war file to a servlet container or an application server and put ws-mock.properties configuration file in the server's classpath.

Examples

Have a look at the maven configuration and some integration tests provided in this showcase application:

Soap Currency Calculator

Soap Currency Calculator is a little sample application calculating currency exchanges. It uses WebserviceX's currency convertor (public SOAP service) to fetch exchange rates for different currencies to calculate exchange amounts. The Sample project contains several integration tests that use SOAP/REST Mock Service to mock WebserviceX's service.

https://sourceforge.net/projects/soaprest-mocker/files/examples/

CXF Circuit Switcher

The CXF Circuit Switcher is an extension of the Apache CXF webservice client. It provides a failover feature witch failback (failover recovery). SOAP/REST Mock Service is used there for integration testing of SOAP and REST client failover and failback.

Changelog

  • 2012-11-13 (v. 1.0.0)
    • initial release
  • 2012-11-18 (v. 1.1.0)
    • accepting json requests/responses
    • changes to the Setup Resources. Setting response delays added. Dedicated delay resource removed.
  • 2012-12-12 (v. 1.2.0)
    • redesigning service API, cosistent and hackable URLs
    • reading SOAP service operations from provided WSDL
    • generating default SOAP responses from WSDL fle
  • 2013-03-23 (v. 1.3.0)
    • adding DEFAULT_RESPONSE_CONTENT_TYPE property defining content type of default responses
    • bug fix: setting up content type for custom responses fixed
    • changes to synchronization of multi-threaded requests
  • 2013-05-14 (v. 1.4.0)
    • bug fix: incorrect document style WSDL parsing
    • relaxing media type constraints for REST requests, allowing vendor specific media types
  • 2013-07-09 (v. 1.5.0)
    • configurable response codes for SOAP responses
    • bug fix: autogenerated default SOAP responses - element values based on WSDL "default" property
  • 2015-04-18 (v. 1.6.0)
    • added a resource to return full data about recorded requests (including http headers, query params etc)

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.