Writing lightweight REST integration tests with the Jersey Test Framework


Writing REST services with JAX-RS (and its reference implementation Jersey) is easy. A class annotated with @Path and some methods with @GET, @POST, … annotations is enough for a fully functional REST service. Real world applications however are more complex. There are request-filters for authorization and access control, context providers for injecting data-access-objects, mappers that convert exceptions to appropriate HTTP responses, MessageBodyReaders and -Writers to convert JSON and XML to and from Java objects, and so on.

All these components can (and should) be tested using unit tests. But this is not enough. To be sure, that these components work together correctly, integration tests are needed. These can be costly to run. They always need the full environment to be configured and running. And the more complex an application, the more complex it is to set up this environment (webserver, database, search engine, message queue, …).

The Jersey Test Framework fills the gap between simple unit tests and full-fledged integration tests. It offers the possibility to write lightweight integration-tests, that do not need any external resources to be available. The web-container, where all components (resources, filters, mappers, …) run, is configured and started on-the-fly. A short introduction to the Jersey Test Framework can be found in the jersey documentation.

Example REST Service and Client

The following explanations are based on a simple example-application. The complete code is available on github. To keep things short, I only included the most interesting parts. And because it’s always interesting, if something goes wrong, I picked a resource, where exceptions are thrown.

public class TodoResource {
    private TodoService todoService;
    // ...
    public void removeTodo(@PathParam("todo") String todoToRemove) {
        // throws a TodoNotFoundException, if the todo can not be found

The TodoService is used to persist todo-items. In the above code, it should remove one item (from the database). If the item does not exist, the method removeTodo throws a TodoNotFoundException. This exception is transformed into a HTTP 404 response by the following exception mapper:

public class NotFoundMapper implements ExceptionMapper {
    public Response toResponse(TodoNotFoundException e) {
        return Response.status(Response.Status.NOT_FOUND)

The mapper not only creates a 404-response, it also packs details about the exception into the response-body (a simple string in this case). This information can be used by clients to find out, what exactly went wrong. In our case, the client throws a ClientSideTodoNotFoundException when he encounters a 404 response with body “todo-not-found”. It could simply throw the same TodoNotFoundException, but in order to be able to distinguish exceptions thrown on client- and server-side, we use a different exception.

public class TodoClient {
    private final String uri;
    public TodoClient(String uri) {
        this.uri = uri;
    public WebResource resource(String todo) {
        return client.resource(uri).path("/todo/"+todo);
    public void removeTodo(String todoToRemove) {
        try {
        } catch (UniformInterfaceException e) {
            int status = e.getResponse().getClientResponseStatus();
            String body = e.getEntity(String.class);
            if (status == Response.Status.NOT_FOUND) &&
                    "todo-not-found".equals(body)) {
                throw ClientSideTodoNotFoundException();
            } else {
                throw e;

Integrated Client-Server-Tests

The following test will check, that any TodoNotFoundException thrown by the TodoService is correctly converted in a HTTP-Response, which the client converts to the appropriate ClientSideTodoNotFoundException. Thus we can test the whole stack (except the database-layer), while still being able to run the tests without external infrastructure (because we mock the database-layer).

class TodoResourceTest extends JerseyTest {
    public static TodoService todoServiceMock = Mockito.mock(TodoService.class);
    public WebAppDescriptor configure() {
        return new WebAppDescriptor.Builder()
                      TodoResource.class.getName() + ";"
                              + MockTodoServiceProvider.class.getName() + ";"
                              + NotFoundMapper.class.getName()).build();
    public TestContainerFactory getTestContainerFactory() {
        return new GrizzlyWebTestContainerFactory();
    @Test(expected = ClientSideTodoNotFoundException.class);
    public void removeTodoShouldThrowNotFoundException() {
        final String todo = "test-todo";
        final TodoClient todoClient = new TodoClient(getBaseURL());
            .thenThrow(new TodoNotFoundException());
    public static class MockTodoServiceProvider extends
           SingletonTypeInjectableProvider {
        public MockTodoServiceProvider() {
            super(TodoService.class, todoServiceMock);

Some explanations:
Because we do not want to connect to an external database, the TodoService has to be mocked. This is done by defining a provider, that injects a mocked TodoService. Because we also want to configure the mock-object inside our test, the MockTodoServiceProvider is defined as inner class and the mock-object is stored in a class variable of our test class.

The test is configured to use a GrizzlyWebTestContainer. See the last part of this blog-post for advantages and disadvantages of using other containers. In the configure() method, we tell jersey, where to find the classes for resources and providers.

In the test method itself, the TodoService mock is instructed to throw a TodoNotFoundException, when the removeTodo() method is called. If everything works correct, then the client will throw the expected ClientSideTodoNotFoundException and the test passes.

Tips and Tricks

What follows is a list of tips, that I hope will be useful for those, who start working with the Jersey Test Framework.

Decide what type of container to use before writing tests
There are two kinds of containers available for the jersey test framework: high-level servlet containers and low-level containers. Both have advantages and disadvantages.

The high-level servlet containers offer the full functionality of a servlet container, automatically injecting instances of HttpServletRequest, … . If your application relies heavily on servlet specific classes, these containers will be your first (and probably only) choice. The servlet functionality comes at a price: All implementations need to open system ports, which makes the tests more fragile and also a little bit slower. Another drawback of using real servlet containers is, that you don’t have direct access to the instances of your resource- and provider-classes. To allow the use of mock-objects, you must work around this problem, for example by assigning context objects to static fields, as we did with the mocked TodoService.

Low-level containers on the other hand, allow you to directly modify the ResourceConfig used. You have direct access to all instances of resource-, provider- and filter-classes used for the rest service. This simplifies mocking. So if you don’t rely on the servlet-api, you’ll probably go for a low-level container.

Do not use WebAppDescriptor for low-level containers
Althoug possible, I do not recommend using WebAppDescriptors for low-level containers. The reason lies in the method LowLevelAppDescriptor.transform(), which is used to transform a WebAppDescriptor to a LowLevelAppDescriptor. The method simply ignores all non-boolean init-params. Moreover, there is a bug when using the property com.sun.jersey.config.property.packages with multiple (colon-separated) package-names. Even if these shortcomings get fixed, you should not rely on the transform() method. The power of low-level containers lies in the possibility to directly modify the used ResourceConfig, which is only possible when using a LowLevelAppDescriptor.

Speedup jersey tests
Because the JerseyTest base class starts a new web-container before each test, the tests are rather slow. One possibility to speed them up, is to start the web-container only once per test-suite. A implementation for a base class doing this is included in the example-application on github.

InMemoryTestContainer with filters
The InMemoryTestContainer is the only container, that does not open any real ports on the system. Of course, being a low-level container, no servlet-specific functionality is available with this container. But if you do not rely on the servlet-api too much, this container is the perfect choice to write really fast and lightweight integration tests.

However, the InMemoryTestContainer has another drawback: you cannot declare any request- or response-filters, because they are overridden by logging filters. To work around this problem, I implemented my own in-memory-test-container (basically only copying the original code and removing the logging filters). The code is also included in the example application.


  • Cosima Laube

    10. August 2012 von Cosima Laube

    Hi Michael,

    thank you for this very helpful post. While reading your code snippets, I noticed that there is a slight mistake in the last listing: line 7 misses a new (return new WebAppDescriptor.Builder()).

    Best regards & happy testing,

    • Michael Lex

      10. August 2012 von Michael Lex

      Hi Cosima,
      I’m glad, that the post was helpful to you. Thank you for pointing out the mistake in the code-snippet. It is fixed now.

      Greetings, Michael

  • Patricio

    11. December 2013 von Patricio

    What version of jersey do you use? latest 1.18 in the configure() it returns an Application object.

  • Max

    Hello, Michael! Thank you for your post!
    What should I do if I wanna test resource with 2 parameters: String and HttpServletRequest, like:

    public Response handle(final String xml, final @Context HttpServletRequest request) {….}

    How right init HttpServletRequest before tests(I need added some headers and parameters) ?

    • Michael Lex

      2. January 2014 von Michael Lex

      Hi Max,
      if you use the Jersey Test Framework, you shouldn’t call the handle() method directly. Instead, you create an HTTP Request using the WebResource class (in my example, this is done inside the TodoClient). With WebResource, you can set any headers you like. The HTTP request is then processed by the embedded WebServer, which then calls the handle() method with the appropriate arguments.

      Note, that you can’t use the InMemoryContainer, if you rely on HttpServletRequest. For this, you need a full-blown Servlet Container, like Grizzly (which is also supported by the Jersey Test Framework).

      Greetings, Michael

  • Bharath

    21. February 2014 von Bharath

    Hi Michael,
    very informative article, it was worth reading completely.
    Could u give any example on High level servlet container and low level container. Right now I’m very new to Jersey Framework and using Tomcat 7, How does it stands there.

    • Bharath

      21. February 2014 von Bharath

      I read this article too, it seems they don’t support tomcat 7.
      Shall i change to some other server and which server it would be good for me. right now I’m using Jersey 1.17 and planning to move to Jersey 2.x in near future.

    • Michael Lex

      28. February 2014 von Michael Lex

      Hi Bharath,
      thank you! If I remember correctly, there is no tomcat container. The only containers I worked with (in the context of the Jersey Test Framework) are the grizzly container (high level) and the in memory container (low level). I also didn’t work with the Jersey Test Framework and Jersey 2 (yet).

      Greetings, Michael

  • Michael A.

    12. March 2014 von Michael A.

    Hi Michael. Great article. I’m using Jersey 2.6 now. A lot has changed. Could you point me to any resources that show how to satisfy the components that may be injected into the RESTful class itself? I’m calling the rest API via the correct URL and I’m constantly getting the exception stating that an instance cannot be injected.

    I would like to be able to mock this dependency and then somehow make it available to the REST class.


  • Zack McKracken

    23. April 2014 von Zack McKracken

    You mention high-level and low-level containers without saying what you mean by that terminology, or into which category the code you use actually falls. You say “low-level containers allow …” but not “a low-level container is …”
    Could you expand a little on this?

  • nowhere

    Hi Michael, is it possible to mock webservice?


Your email address will not be published.