Category Archives: Articles in English

WS testing

This post recaps some results of my experiments with WS testing. In last few months I have been working on several projects – Spring WS Test, Spring WS 2.0 testing support and finally on Smock. All of them reflect different approaches to WS testing. Today I am going recapitulate my findings focusing on testing producer/server side code. Consumer/client side will be covered in a following post.

Simple service, simple test

You may wonder what’s the problem? Testing web services is easy. We just need to call the endpoint end verify the response. For a simple web service we can write a simple test like this

@Test
public void testPlus()
{
	assertEquals(3, endpoint.plus(1, 2));
}

The test is same as if I was testing a normal method.

Web Services tend to be complex

The trouble is that web services tend to be complex. Normal Java methods usually have few relatively simple parameters. On the other hand, web service request or response could be quite complicated which makes the service endpoint hard to test.

GetFlightsRequest request = new GetFlightsRequest();
request.setFrom("PRG");
request.setTo("DUB");
request.setServiceClass(ServiceClass.BUSINESS);
request.setDepartureDate(DatatypeFactory.newInstance().newXMLGregorianCalendarDate(2011, 02, 23, 0));
//more setter calls could be here
		
GetFlightsResponse response = endpoint.getFlights(request);

List<Flight> flights = response.getFlight();
assertEquals(1, flights.size());
assertEquals(ServiceClass.BUSINESS, flights.get(0).getServiceClass());
//more assertions here

Such tests are bearable only until certain level of complexity. From certain level it’s real pain. I really hate to call twenty setters to construct several levels of nested XML hierarchy and then to call dozens of getters to validate the response.

To define XML use … the XML
The problem is that we want to create or validate an XML structure using wrong language. Java is just not suitable for the task. The best language to describe XML is, surprise, surprise, the XML. Would not it be easier to create XML files containing the request and response and just use them in the test?

GetFlightsRequest request = JAXB.unmarshal(getStream("request1.xml"), GetFlightsRequest.class);
		
GetFlightsResponse response = endpoint.getFlights(request);
		
DOMResult domResponse = new DOMResult();
JAXB.marshal(response, domResponse);
		
XMLUnit.setIgnoreWhitespace(true);
XMLAssert.assertXMLEqual(getDocument("response1.xml"), (Document)domResponse.getNode());

It’s much better. This test will look exactly the same way regardless the complexity of the service. But it still have some shortcomings. The biggest one is that usually testing using only one request is not sufficient. I’d like to test the service using different inputs. In such case I have to create lot of XML files that differ just in few elements. It’s a maintenance nightmare. If you change the service, you also have to change all the XML files.

Smock comes to help
Up until now we managed to test without any special framework except XMLUnit. Now we will start to use my precious Smock library. The test above can be rewritten to this form.

Map<String, Object> params = new HashMap<String, Object>();
params.put("from", "DUB");
params.put("to", "JFK");
params.put("serviceClass", "economy");
GetFlightsRequest request = createRequest(
					withMessage("request-context-groovy.xml")
					.withParameters(params), GetFlightsRequest.class);

GetFlightsResponse response = endpoint.getFlights(request);

validate(response, request)
	.andExpect(message("response-context-groovy.xml")
	.withParameter("serviceClass", "economy"));

The test is quite similar as the previous one. The difference is that it uses statically imported method createRequest to create a request and validate method to validate the response. The main advantage is that Smock methods support templates. So we can set just values we want to, the rest can be driven by the template. Moreover we do not need to deal with the request structure, parameters can be set into a simple flat map.

<ns1:GetFlightsRequest>
	<ns1:from>${from}</ns1:from>
	<ns1:to>${to}</ns1:to>
	<ns1:departureDate>2001-01-01</ns1:departureDate>
	<ns1:serviceClass>${serviceClass}</ns1:serviceClass>
</ns1:GetFlightsRequest>

Templates are even more useful when comparing the response

<ns3:GetFlightsResponse>
	<ns3:flight>
		<ns2:number>OK1324</ns2:number>
		<ns2:departureTime>2011-02-19T10:00:00</ns2:departureTime>
		<ns2:from>
			<ns2:code>${GetFlightsRequest.from}</ns2:code>
			<ns2:name>${IGNORE}</ns2:name>
			<ns2:city>${IGNORE}</ns2:city>
		</ns2:from>
		<ns2:arrivalTime>2011-02-19T12:00:00</ns2:arrivalTime>
		<ns2:to>
			<ns2:code>${GetFlightsRequest.to}</ns2:code>
			<ns2:name>${IGNORE}</ns2:name>
			<ns2:city>${IGNORE}</ns2:city>
		</ns2:to>
		<ns2:serviceClass>${serviceClass}</ns2:serviceClass>
	</ns3:flight>
</ns3:GetFlightsResponse>

We can ignore some elements, we can compare values based on the request elements and so on. Moreover, when we are using Smock library, we can leverage Spring WS 2.0 testing capabilities that Smock builds on. We can for example validate that the response is valid regarding to its schema.

validate(response).andExpect(validPayload(resource("xsd/messages.xsd")));

Cool, isn’t it?

Testing the configuration
Sometimes unit test are not sufficient. Sometimes we want to test the configuration, interceptors, error handling and so on. No problem. If you are using Spring WS 2, you can use the built-in testing library. If you need templates or if you are using different framework like Axis 2, you can use Smock. The test looks similar.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring-ws-servlet.xml")
public class GroovyEndpointTest {

	private MockWebServiceClient wsMockClient;
	
	@Autowired
	public void setApplicationContext(ApplicationContext context)
	{
		wsMockClient = createClient(context);
	}
	

	@Test
	public void testResponseTemplate() throws Exception {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("from", "DUB");
		params.put("to", "JFK");
		params.put("serviceClass", "economy");
		wsMockClient.sendRequest(
			withMessage("request-context-groovy.xml")
			  .withParameters(params))
			.andExpect(message("response-context-groovy.xml")
			  .withParameter("serviceClass", "economy"));
	}

The only difference is that we have to bootstrap the application context. Having done this, we can use the mock web service client to call our services. Even though this kind of tests is more complicated, we can use it to test object-XML mapping, endpoint resolution, error handling and configuration in general.

We have seen several different methods of WS testing. Each of them have advantages and disadvantages. If you keep you services simple, your tests are simple too. If the service is more complex, it makes sense to use XML for the test. Either using your own helper methods, Spring WS 2.0 test support or Smock.

All the samples could be downloaded from here.

Where does this class came from?

Today I have been debugging some nasty problem on Weblogic. The application worked on one version but did not work on an older one. Apparently some classes were not compatible. But it’s quite difficult to debug such problem. You need to find out from which JAR given class was taken from. It’s not trivial in enterprise environment. The class can be part of J2SE, application server and your EAR at the same time. Especially if the class has something to do with XML or web services. End if you have such class, you need some trick to determine which version was actually used.

The trick is simple yet not widely known. In fact I have encountered it in a Scala related article. You just call this code from JSP or some other suitable place.

YourClass.class.getProtectionDomain().getCodeSource().getLocation()

And that’s all, this command will return path to your mystery class JAR.

Kindlology

Most readers get as far as the Future Semiconditionally Modified Subinverted Plagal Past Subjunctive Intentional before giving up; and in fact in later editions of the book all pages beyond this point have been left blank to save on printing costs.

Hitchhiker’s Guide to the Galaxy

I am new Kindle user and the more I use it, the more I like it. Although it probably will never have the same feeling as reading a book there are two features that gives it some edge.

  1. It’s always with me. Even if I do not have it in my backpack, I do have my Android cell phone with Kindle app installed. And what’s best, the application knows where I have stopped reading and I can simply continue.
  2. Highlights and bookmarking are much better. Even if I have pencil when reading a book the highlights are hard to find. I love to quote authorities. But it’s always hard to find the right page even though I have underlined it. Kindle solves it quite well. You can highlight whatever you want, you can search the notes and highlights, you can access it on-line and you can even tweet it right from the device. You can even see paragraphs frequently highlighted by other readers! (Although I am thinking about switching this feature off, it’s a bit disturbing.)

But I do not want to praise Kindle here, I’d like to think about the consequences. There is the other side of the coin. To be able to implement this features, Amazon has to know about every page turn you make. It brings some privacy issues, but I do not want to talk about that neither.

I’d like to imagine how such data could be used for “scientific” purposes. I’d like to know what’s my reading speed. Is it lower in the evening? Is it faster when reading thrillers? What’s European reading speed? Is it higher than American? Do I skip paragraphs? Do other readers skip the same paragraphs? Is there some part of given book that force people to take a break? Do people make more notes at the beginning of the book? Is there a book that readers usually do not finish? What’s the finish rate in general? Are there some books that people just buy but do not even start to read?

You see, there is lot of questions that we can finally find answers for. The only think we need is to persuade Amazon to publish the data and some PhD students to do the statistics. Even without that the data give some interesting result right now. You can see that readers make highlights in fiction books like Eat Pray and Love. I would not expect that. You can see it yourself on http://kindle.amazon.com

PS: I am not the first one who had the same idea, here is one of my predecessor’s articles.

Kindle Bookmarks