How to write Unit Test for this class using Jersey 2 test framework

java, jersey, jersey-2.0, rest, unit-testing

Solution

You can use the HK2 capabilities of Jersey 2, that helps with Dependency Injection. Doing it this way, you can create a `Factory` for `HttpServletRequest` and return the mock from your `RequestHelper`. For example

public class HttpServletRequestFactory implements Factory<HttpServlet> {

    @Override
    public HttpServletRequest provide() {
       return RequestHelper.getMockServletRequest();
    }

    @Override
    public void dispose(HttpSession t) {
    }
}

Then in your `JerseyTest` subclass, just register an `AbstractBinder` with the `ResourceConfig`. For example

@Override
public Application configure() {
    ResourceConfig config = new ResourceConfig(...);
    config.register(new AbstractBinder(){
        @Override
        public void configure() {
            bindFactory(HttpServletRequestFactory.class).to(HttpServletRequest.class);
        }
    });
} 

Another option

...is to not mock the `HttpServletRequest` at all, and use the actual `HttpServletRequest`. To do that, we need to configure the `DeploymentContext` as we override the `getDeploymentContext()`, and return a `ServletDeploymentContext`. You can see an example here and here. The first has also has an example of using a `Factory`, while the second show an example of how to configure based on web.xml settings. If you chose the case for mocking the `HttpServletRequest`, then you wouldn't need to override the `getTestContainerFactory` and `configureDeployment` as seen in the examples. Simply using the `Application configure()` override is enough, as long as nothing else is dependent on servlet features.

The examples in the link use

<dependency>
    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
    <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
    <version>${jersey.version}</version>
</dependency>

Extra

Both the example I linked to are trying to take advantage of the Sevlet features. So I'll give a complete example of using a request mock.

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Assert;
import org.junit.Test;

public class MockHttpSevletRequestTest extends JerseyTest {

    @Path("http")
    public static class HttpResource {
        @GET
        public Response getResponse(@Context HttpServletRequest request) {
            return Response.ok(request.getMethod()).build();
        }
    }

    @Override
    public Application configure() {
        ResourceConfig config = new ResourceConfig(HttpResource.class);
        config.register(new AbstractBinder() {
            @Override
            public void configure() {
                bindFactory(HttpServletRequestFactory.class)
                        .to(HttpServletRequest.class);
            }
        });
        return config;
    }

    public static class HttpServletRequestFactory implements Factory<HttpServletRequest> {

        @Override
        public HttpServletRequest provide() {
            return new MockHttpServletRequest();
        }

        @Override
        public void dispose(HttpServletRequest t) {
        }
    }

    @Test
    public void test() {
        String response = target("http").request().get(String.class);
        System.out.println(response);
        Assert.assertEquals("POST", response);
    }
}

`MockHttpServletRequest` is simple a dummy implementation of `HttpServletRequest` where I only override one method `getMethod()` and always return `POST`. You can see from the result, that even though it's a `get` request, it still returns `POST`

public class MockHttpServletRequest implements HttpServletRequest {

    @Override
    public String getMethod() {
        return "POST";
    }
    ...
}

Problem

I am trying to write unit test for a Rest api call which is having a POST method for adding a video file to web based application using Jersey2. Here is the signature of the method of my class(`TemplateController.java`) for which I want to write unit test: ``` @POST @Path("/video/add") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response addVideoData( @Context HttpServletRequest request, AttachmentDTO attachmentDTO) { ... } ``` Here is my test method of the test class (`TemplateControllerUnitTestCase.java`): ``` @Test public void videoAdd_requestObjectIsNull_ResponseStatusIsOK() throws Exception { // arrange Builder builder = target("/target/video/add").request(); // action final Response response = builder.post(Entity.entity(attachemntDTO, MediaType.APPLICATION_JSON)); // assertion ... } ``` I'm able to pass the `AttachmentDAO` object to the `TemplateController` class from test class but unable to pass the request object which is becoming null in the `method(addVideoData())` of the `TemplateController.java class`. I'm using `RequestHelper` class which is a helper class for `HttpServletRequest`, so I want to pass an object of this class to the `method(addVideoData())` using Jersey2 test framework.

Original source

Related problems