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"/> </bean> </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(); } }