Last few weeks I have been working on one of my pet projects. Its name is Spring WS Test. As the name implies, its main purpose is to simplify Spring WS tests.
Again, I am scratching my own itch. I am quite test infected and I have needed something that allows me to write functional tests of my application without having to depend on an external server. Until now, you basically had two options. This first one is to test WS client application using plain old JUnit together with a library like EasyMock. But usually this test are quite ugly and hard to read. Moreover this type of tests does not test your configuration. The second option is to create a functional test that calls an external mock service. But this solution requires you to have two JVM, its configuration is complicated and error prone.
I have been looking for something in between, for something that would allow me to write functional tests using JUnit and would be able to run in the same JVM as the test. Unfortunately I have not been able to find anything similar.
That’s the reason why I have created Spring WS Test project. It’s quite simple and easy even though I had to spent lot of my evenings getting it into a publishable state.
Basic configuration looks like this
<beans ...>
<!-- Creates mock message sender -->
<bean id="messageSender" class="net.javacrumbs.springws.test.MockWebServiceMessageSender"/>
<!-- Injects mock message sender into WebServiceTemplate -->
<bean class="net.javacrumbs.springws.test.util.MockMessageSenderInjector"/>
<!-- Looks for responses on the disc based on the provided XPath -->
<bean class="net.javacrumbs.springws.test.generator.DefaultResponseGeneratorFactoryBean">
<property name="namespaceMap">
<map>
<entry key="soapenv"
value="http://schemas.xmlsoap.org/soap/envelope/"/>
<entry key="ns"
value="http://www.springframework.org/spring-ws/samples/airline/schemas/messages"/>
</map>
</property>
<property name="XPathExpressions">
<list>
<value>
concat(local-name(//soapenv:Body/*[1]),'/default-response.xml')
</value>
</list>
</property>
</bean>
</beans>
Here we have MockWebServiceMessageSender that replaces standard Spring WebServiceMessageSender. The replacement is done by MockMessageSenderInjector. The only other thing you have to do is to define ResponseGenerator. It’s main purpose is to look for files in you test classpath and return them as mock responses.
Of course it has to decide, which file to use. By default a XPath expression is used to determine the resource name. In our example it is concat(local-name(//soapenv:Body/*[1]),'/default-response.xml')
. It takes name of the payload (first soap:Body child) and uses it as a directory name. File “default-response.xml” from this directory is used as the mock response. Simple isn’t it?
Of course you can define more complicated XPaths, you can use XSLT templates to generate your responses, you can validate your requests etc. More details can be found in the documentation.
Now I am looking for some end-user feedback. So please, if you are using Spring WS on the client side do not hesitate and test it. It should be stable enough to be used although there might be a bug here and there.