Friday, March 1, 2013

Increase quality and productivity with the Jersey Test Framework

Note:  This article applies to Jersey 1.x.  If you're looking for information on how to use the Jersey Test Framework in Jersey 2 please see this more recent article.

With the Jersey test framework developers can increase the quality of their software as well as their productivity without leaving the comfort of their favorite IDE.

The framework spins up an embedded servlet container that is configured to load the restful resources specified by the developer. In addition, the SpringServlet can be used to wire in the necessary beans if Spring is being used.

And, this is really super simple. The key is to extend the JerseyTest class and override the configure() method. In the configure() method you supply the same information that you would normally provide in your web.xml.

Line 5 : specify the package that contains the Jersey resource(s) you want to test
Line 6 : provide the name and location of the Spring context file (if using Spring)
Line 7 : turn on the JSON to POJO mapping feature if you want to use that

public class MyResourceWebServiceTest extends JerseyTest {

    @Override
    protected AppDescriptor configure() {
        return new WebAppDescriptor.Builder("com.mycompany.services")
            .contextParam("contextConfigLocation", "classpath:**/testContext.xml")
            .initParam("com.sun.jersey.api.json.POJOMappingFeature", "true")
            .servletClass(SpringServlet.class)
            .contextListenerClass(ContextLoaderListener.class)
            .requestListenerClass(RequestContextListener.class)
            .build();
    } // configure()
Once your test class is configured to spin up the embedded web container with your resources now it's time to write your tests. Again, the Jersey test framework makes it so easy even a caveman can do it.

On line 3 below we simply access a WebResource object and provide the relative URI to the resource we are interested in. This URI should match the @Path mappings in your Jersey resource definition.

Once the WebResource is defined simply use it to build and execute the HTTP request for the desired HTTP method, in this case GET, as shown on line 6. That's it. All that's left to do is the standard JUnit stuff to validate the response.
    @Test
    public void someTest() {
        WebResource webResource = resource().path("/some/resource/17");
        ClientResponse response =  webResource
            .accept(MediaType.APPLICATION_JSON)
            .get(ClientResponse.class);

        assertEquals(200, response.getStatus());

        try {
            JSONObject obj = new JSONObject(response.getEntity(String.class));
            assertEquals("widget", obj.get("type"));
        } catch (JSONException e) {
            fail(e.getMessage());
        }
    } // someTest()

Now, push a button or hit a key or two to kick off your JUnit test suite and watch your Jersey web services and tests fly.  If you need to make a change it only takes a minute or two to modify your code and run the tests again.

One piece of advice - create a test specific Spring context file targeting the exact REST resources you want to test and, if your resources eventually end up accessing some datasource (most would), consider injecting mock data access objects into your Spring beans so you can easily control the data that your resource would have access to, thus easily facilitating your testing (and development) and making your tests repeatable.

See this post if you want to learn how to easily create hyperlinks in your Jersey REST services.

See this post if you want to see more examples of Jersey unit testing or comparisons of different ways to marshall your data/objects.