Embracing the Messiness in Search of Epic Solutions

Spring Web Services: Client Integration Testing with MockWebServiceServer

Posted

in

Spring Web Services provides a great way to perform web service client integration tests. However, the example in the documentation requires the client class to extend org.springframework.ws.client.core.support.WebServiceGatewaySupport, which is rather ugly. Instead, I prefer to have WebServiceTemplate injected into my client class.

So, I made a slight tweak to my integration test to work this work…

Production Code To Be Tested

First, we need the following Spring Web Services dependency:

<dependency>
    <groupid>org.springframework.ws</groupid>
    <artifactid>spring-ws-core</artifactid>
    <version>2.1.4.RELEASE</version>
</dependency>

Let’s assume the client class looks like this:-

@Service
public class WSClientServiceImpl implements WSClientService {

    private WebServiceTemplate webServiceTemplate;

    @Autowired
    public WSClientServiceImpl(WebServiceTemplate webServiceTemplate) {
        this.webServiceTemplate = webServiceTemplate;
    }

    public String login(String username, String password) {
        Login login = new ObjectFactory().createLogin();
        login.setUsername(username);
        login.setPassword(password);

        SoapActionCallback callback = new SoapActionCallback("http://webservice/login");
        Object object = webServiceTemplate.marshalSendAndReceive(login, callback);

        JAXBElement<string> jaxbElement = (JAXBElement<string>) object;
        String sessionId = jaxbElement.getValue();

        return sessionId;
    }
}

The WebServiceTemplate bean is configured like this:-

<beans ...="">
    <context:component-scan base-package="com.choonchernlim.epicapp">


    <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <property name="contextPaths">
            <list>
                <value>...</value>
            </list>
        </property>
    </bean>

    <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
        <property name="marshaller" ref="marshaller">
        <property name="unmarshaller" ref="marshaller">
        <property name="defaultUri" value="http://webservice">
    </property></property></property></bean>
</context:component-scan></beans>

Constructing Integration Test

Make sure we have the Spring Web Services Test framework dependency:-

<dependency>
    <groupid>org.springframework.ws</groupid>
    <artifactid>spring-ws-test</artifactid>
    <version>2.1.4.RELEASE</version>
    <scope>test</scope>
</dependency>

The integration test looks similar to the example in the Spring documentation, however, I injected WebServiceTemplate instead:-

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath*:applicationContext.xml"})
public class WSClientServiceImplTest {

    @Autowired
    private WSClientService wsClientService;

    @Autowired
    private WebServiceTemplate webServiceTemplate;

    private MockWebServiceServer mockServer;

    @Before
    public void createServer() throws Exception {
        mockServer = MockWebServiceServer.createServer(webServiceTemplate);
    }

    @Test
    public void testLogin() {
        Source requestPayload = new StringSource(
                "<ns2:login xmlns:ns2="http://webservice/login">" +
                "  <ns2:username>user</ns2:username>" +
                "  <ns2:password>password</ns2:password>" +
                "</ns2:login>"
        );

        Source responsePayload = new StringSource(
                "<sessionid xmlns="http://webservice/login">12345</sessionid>"
        );

        mockServer.expect(payload(requestPayload)).andRespond(withPayload(responsePayload));

        String sessionId = wsClientService.login("user", "password");

        assertThat(sessionId, is("12345"));

        mockServer.verify();
    }
}

Comments

One response to “Spring Web Services: Client Integration Testing with MockWebServiceServer”

  1. Dan Avatar
    Dan

    I’m getting java.lang.AssertionError: Further connection(s) expected. Any idea if I’m missing anything?

Leave a Reply