Skip to content

aukevanleeuwen/mockito-soap-cxf

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

63 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status

mockito-soap-cxf

SOAP web-service mocking utility which creates real service endpoints on local ports using webserver instances. These endpoints delegate requests directly to mocks.

Users will benefit from

  • full stack client testing
    • interceptors
    • handlers
  • simple JUnit Rule setup
  • SOAP-Fault helper

all with the regular advantages of Mockito.

Bugs, feature suggestions and help requests can be filed with the issue-tracker.

License

Apache 2.0

Obtain

The project is based on Maven and is available form central Maven repository.

Example dependency config:

<dependency>
    <groupId>com.github.skjolber</groupId>
    <artifactId>mockito-soap-cxf</artifactId>
    <version>1.0.3</version>
    <scope>test</scope>
</dependency>

CXF version < 3

Add an exclusion for the cxf-core artifact

<exclusions>
    <exclusion>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-core</artifactId>
    </exclusion>
</exclusions>

Usage

If you prefer skipping to a full example, see this unit test.

Basics

Create a SoapServiceRule

@Rule
public SoapServiceRule soap = SoapServiceRule.newInstance();

and mock service endpoints by using

MyServicePortType serviceMock = soap.mock(MyServicePortType.class, "http://localhost:12345"); 

or, preferably

MyServicePortType serviceMock = soap.mock(MyServicePortType.class, "http://localhost:12345", "classpath:/wsdl/MyService.wsdl"); 

for schema validation. The returned serviceMock instance is a normal Mockito mock(..) object.

Details

Create mock response via code

// init response
GetAccountsResponse mockResponse = new GetAccountsResponse();
List<String> accountList = mockResponse.getAccount();
accountList.add("1234");
accountList.add("5678");

or from XML

GetAccountsResponse response = jaxbUtil.readResource("/my/test/GetAccountsResponse1.xml", GetAccountsResponse.class);

using your favorite JAXB utility. Then mock

when(serviceMock.getAccounts(any(GetAccountsRequest.class))).thenReturn(mockResponse);

and apply standard Mockito test approach. After triggering calls to the mock service, verify number of method calls

ArgumentCaptor<GetAccountsRequest> argument1 = ArgumentCaptor.forClass(GetAccountsRequest.class);
verify(serviceMock, times(1)).getAccounts(argument1.capture());

and request details

GetAccountsRequest request = argument1.getValue();
assertThat(request.getCustomerNumber(), is(customerNumber));

SOAP Faults

Mock SOAP faults by adding import

import static com.skjolberg.mockito.soap.SoapServiceFault.*;

then mock doing

when(serviceMock.getAccounts(any(GetAccountsRequest.class))).thenThrow(createFault(exception));

or mock directly using an XML string / w3c DOM node.

SOAP service mock as a field

Wrap mock creation using a @Before method if you prefer using fields for your mocks:

@Value("${bankcustomer.service}")
private String bankCustomerServiceAddress;

private BankCustomerServicePortType serviceMock;

@Before
public void mockService() {
	serviceMock = soap.mock(BankCustomerServicePortType.class, bankCustomerServiceAddress);
}

MTOM (binary attachments)

CXF SOAP clients support MTOM of out the box, enable MTOM in the service mock using

serviceMock = soap.mock(BankCustomerServicePortType.class, bankCustomerServiceAddress, properties("mtom-enabled", Boolean.TRUE));

and add a DataHandler to the mock response using

byte[] mockData = new byte[] {0x00, 0x01};
DataSource source = new ByteArrayDataSource(mockData, "application/octet-stream");
mockResponse.setCertificate(new DataHandler(source)); // MTOM-enabled base64binary

See MTOM unit test for an example.

Running in parallel

For use-cases which require test-cases to run in parallel, it is possible to mock endpoints on random (free) ports. For the SoapEndpointRule methods

@ClassRule
public static SoapEndpointRule soap = SoapEndpointRule.newInstance("myPort", "yourPort");

or with port range

@ClassRule
public static SoapEndpointRule soap = SoapEndpointRule.newInstance(10000, 30000, "myPort", "yourPort");

there will be reserved two random free ports. Ports numbers can be retrieved using.

int myPort = soap.getPort("myPort");

and

String myPort = System.getProperty("myPort");

In other words, for property resolvers which include system-properties, the reserved ports are readible available. For example the Spring property expression

http://localhost:${myPort}/selfservice/bank

would effectively point to the mocked webservice at myPort. For a more complete example, see this spring unit test.

Troubleshooting

There seems to be an issue with the use of the -exsh parameter for passing headers into the mock and schema validation. Rather than supplying the wsdl location, supply the XSD locations to work around the problem until a solution can be found.

CXF version 2.x

If you see exception cause by

No binding factory for namespace http://schemas.xmlsoap.org/soap/ registered.

then you're mixing CXF version 2 and 3 - see above about excluding cxf-core artifact.

History

  • 1.0.3: MTOM support
  • 1.0.2: Support for mocking on (random) free ports (via SoapEndpointrule).
  • 1.0.1: Improved JAXB helper methods in SoapServiceFault
  • 1.0.0: Initial versionn

About

Test SOAP services using JUnit and Mockito

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java 100.0%