Saturday, January 17, 2009

Testing REST Services with Groovy

For awhile now, RIAs (Rich Internet Applications) have rapidly started replacing traditional server-side web applications (JSP, JSF, etc). Typically, these flashier sites are created using Flex or javascript libraries like extjs or yui. At the heart of these sexy applications live simple REST services that return JSON or XML.

Testing these REST services should be made a high priority for several reasons:

  1. It's the contract between the client and server. Breaking that contract should be avoided.
  2. Your application may not be the only client. Once external parties start consuming your REST services you'll want tests in place to ensure you don't break their clients.
  3. To validate the response is well-formed XML or properly constructed JSON
  4. Valuable black-box test, testing the entire server-side stack starting from the REST layer going all the way down to the DAO layer to the database.
So, what's the easiest way to test REST services? For awhile now I have been combing the internet for the best tools to accomplish this goal, since I wasn't going to do it in pure Java, and I think I finally found the right combination using Groovy and HttpBuilder. Groovy because its super easy to parse XML and JSON, and HttpBuilder because it's a great wrapper for the popular Apache Commons HTTP Client library.

Now let's say you have a REST service at the URL http://localhost:8080/myapp/api/books that returns this JSON:
{"books":[
{"name":"Being Mad","author":"Kit Plummer"},
{"name":"Clown Life","author":"Josh Hoover"},
{"name":"You Miss Me","author":"Ron Alleva"},
{"name":"Talk to me Goose","author":"Jeff Black"}
]}
This is how simple it is to write a test in Groovy using HttpBuilder:
import groovyx.net.http.HTTPBuilder
import groovyx.net.http.Method
import static groovyx.net.http.ContentType.JSON

class BooksTest extends GroovyTestCase {
def void test_get_all_books() {
def http = new HTTPBuilder("http://localhost:8080")

http.request(Method.valueOf("GET"), JSON) {
url.path = '/myapp/api/books'

response.success = {resp, json ->
json.books.each { book ->
assert book.name != ""
}
}
}
}
}

To me the major advantage to this approach is being able to traverse the JSON response like I would in javascript. If the response was XML it be just as easy too.

The only two remaining items you would need would be adding the gmaven plugin to your pom and httpbuilder as a dependency.