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.
Lukáš, thank you for the efforts. It looks really interesting. Next time I get back to my Spring WS related code I’ll give it a try for sure. So far I used soapUI and it worked fine, but a more lightweight testing tool should be pretty enough in some cases.
Im using ttry your spring ws test but the class WsMockControlTestExecutionListener is unknow.
please can you help me .
Regards
Please, check that spring-ws-test-0.10.jar on in your classpath. If it is, please send me more details to my e-mail address lukas the funny a in the circle krecan dot net.
Just wanted to share a related post (with topic, Building a web service with Spring-WS) at
http://justcompiled.blogspot.com/2010/09/building-web-service-with-spring-ws.html
Hi Lukas,
Thanks a lot for coming up with the idea this certainly eases a gr8 deal of effort we put in terms of simulations which we do for unit testing. However, i’m trying to work out for a solution to resolve similation problem with one of our WS client call. By using WsMockControl is there a way by which i can enable mock engine to ignore few elements in my request payload (as these values are bound change dynamically)
Thanks in advance !
Rahul
Hi Rahul,
Spring-WS test does not support it out of the box, but you have the following options
1) Do not validate the request.
2) Use XPath validaton
3) Use custom validator (WsMockControl.validate method)