susestudio/susestudio-lib-java — pull request #10 by SilvioMoioli (2013-02-16 10:03:49+00:00)
Title: HTTP interface tests

I have an opinionated code contribution today, and hope you will like the result!

Motivation: current tests cover what arguably is the most critical and complex aspect of the library: SUSE Studio's XML interpretation, but they cover little else. In particular, I felt a need of tests that cover the translation of Java method calls to HTTP requests, and the correct reception of HTTP responses.

Proposed solution: integrating a (mock) Web server in the test suite and calling SUSEStudio methods on that. The server would "record" requests as they are received, later exposing them to test code for assertions. In addition to that, it would provide a mechanism to let test code decide how to respond so that HTTP response reception can be tested as well.

Pros: it is possible to test that HTTP requests are produced as intended, and that responses are correctly read, at "wire level".
There is no need of adding further indirection to current code.
Since I chose [a particularly lightweight Web server implementation](http://www.simpleframework.org/), these produced tests run fast - on average 30ms on my three-year old hardware.
The approach is, in principle, completely reusable in other contexts. In fact classes in com.suse.studio.client.test.httpservermock do not depend on anything Studio-specific, nor anything JUnit-specific for that matter. They could even be refactored in a separate library!
A couple of Studio-specific convenience classes were also added in the test.util package to ease test writing.
Thread and socket handling is completely transparent to the user.

Cons: it can be argued that this code is not 100% unit-test styled since it does not test "only one aspect at a time" but the whole API call.
It is also not as clean or simple as, say, [WebMock](https://github.com/bblimke/webmock) for Ruby, since no monkey-patching is allowed in Java. Actually I wrote this because I am not aware of any existing/standard ways to extend JUnit to do HTTP client testing other than rolling my own.

How it works: test code should define a method that makes an HTTP request to localhost:1234, and a method that can respond to it. Since Java does not have out-of-the-box closures (sigh), those must be wrapped in objects that implement the Callable and Responder interfaces. HttpServerMock will then run them and return an ExchangeDetails object with request and response information to use for assertions.
Convenience requester class SUSEStudioRequester will automatically set up a SUSEStudio object, while TestExampleResponder will respond with an XML file from the "examples" resource folder.

Next possible step: integrating XML parsing assertions to create complete "integration" tests (at the moment only HTTP I/O is tested here, parsing tests are left by themselves). This would probably be bad for style, but I think it would be handy to have while implementing the next APIs, since it would allow to test them without writing "main" programs, even without accessing Studio (in principle). I would definitely like to know your opinion before going ahead on this, anyway.

Any comments are more than welcome!