user2108383
user2108383

Reputation: 277

How to write a test case for Jersey Rest resouce + Grizzly+mockito

I am trying to write integration test case for Jersey Using Grizzly and Mockito, Spring, I am not able to mock the service Class. how can I mock the service class which is injected in my Resource class with @AutoWired

@AutoWired
MyFirstService myFirstServiceImpl;

@AutoWired
MySecondService mySecondServiceImpl;

    @GET
        @Path("/abc")
        @Consumes(MediaType.APPLICATION_JSON)
        @Produces(MediaType.APPLICATION_JSON)
        public Response getDetails(@QueryParam("xyz") String xyz,
            @QueryParam("pqr") String pqr) {
                    Gson gson = new Gson();
            Map<String, Object> someMap= new HashMap<String, Object>();
            try {

                map.put("a", myFirstServiceImpl.getSomeDetails(xyz);

                map.put("b", mySecondService.getSomeMoreDetails(pqr);
            } catch (Exception e) {
                e.printStackTrace();
            }

            return Response.status(200).entity(gson.toJson(someMap)).build();

        }


Test Class:


@Mock
    private static MySecondService mySecondServiceImpl;;
    @Mock
    private static MyFirstService myFirstServiceImpl;

    @Before
    public void initMocks() {
        resource = new MyResource();
        MockitoAnnotations.initMocks(this);
        resource.setMyFirstService (firstService);
        resource.setSecondService(secondService);

    }

 @Override
    protected TestContainerFactory getTestContainerFactory() {
        return new GrizzlyWebTestContainerFactory();
    }

    private DeploymentContext getRestResourcesWithFilter() {
        System.setProperty("jersey.config.test.container.port", "8104");

        ServletDeploymentContext context =
            ServletDeploymentContext
                .forServlet(
                    new ServletContainer(new ResourceConfig(MyResource.class).property(
                        ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, "true")))
                .addListener(ContextLoaderListener.class).addListener(RequestContextListener.class)
                .initParam("contextConfigLocation", "classpath:applicationContext.xml")
                .build();
        return context;

    @Test
    public void test() throws Exception {
        SomeOBject object= new SomeObject();

        Object2 obj= new Object2();



        when(myFirstServiceImpl.getSomeDetails(any(String.class))).thenReturn(object);
       when(mySecondService.getSomeMoreDetails(pqr)).thenReturn(obj);

         Response response = target("v1/abc").request().get();

    }

This Test case is passing but the service class which I mocked are not mocking I am getting null pointer exception when ever code hits that line

Upvotes: 1

Views: 1995

Answers (1)

Paul Samsotha
Paul Samsotha

Reputation: 208944

So there are a couple problems

  1. The @Before method. JerseyTest already implements a @Before method, where it creates the test container. So your mocks won't be created in time and the services will be null. Best thing to do is to just create the services in the configureDeployment() method, where you are initializing the Jersey application. A new container will be created for each test case, so you will have new mocks for each test.

  2. You are simple passing the class to the ResourceConfig constructor, which will cause the Jersey runtime to create the instance of the resource class. So after you create the resource class, instead of new ResourceConfig(MyResource.class), do new ResourceConfig().register(resource).

So the configureDeployment() method should look more like

@Override
public DeploymentContext configureDeployment() {
    resource = new MyResource();
    MockitoAnnotations.initMocks(this);
    resource.setMyFirstService(firstService);
    resource.setSecondService(secondService);

    ServletDeploymentContext context
            = ServletDeploymentContext.forServlet(
                    new ServletContainer(new ResourceConfig().register(resource).property(
                                    ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, "true")))
            .build();
    return context;
}

Another problem is that you are not actually passing any query parameters in the request. So in your resource method, the parameters will be null. Your request should look more like

target(...).queryParam(key1, value1).queryParam(key2, value2)

Here is a complete test

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import junit.framework.Assert;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.ServletDeploymentContext;
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

public class MockitoTest extends JerseyTest {

    public static interface Service {

        String getMessage(String name);
    }

    @Mock
    private Service service;

    @Path("mock")
    public static class MyResource {

        private Service service;

        public void setService(Service service) {
            this.service = service;
        }

        @GET
        public String get(@QueryParam("name") String name) {


            return service.getMessage(name);

        }
    }

    @Override
    public DeploymentContext configureDeployment() {

        MyResource resource = new MyResource();
        MockitoAnnotations.initMocks(this);
        resource.setService(service);

        ServletDeploymentContext context
                = ServletDeploymentContext.forServlet(
                        new ServletContainer(new ResourceConfig().register(resource).property(
                                        ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, "true")))
                .build();
        return context;
    }

    @Override
    protected TestContainerFactory getTestContainerFactory() {
        return new GrizzlyWebTestContainerFactory();
    }

    @Test
    public void doTest() {

        Mockito.when(service.getMessage(Mockito.anyString())).thenAnswer(new Answer<String>(){
            @Override
            public String answer(InvocationOnMock invocation) throws Throwable {
                return "Hello " + (String)invocation.getArguments()[0];
            }
        });

        Response response = target("mock").queryParam("name", "peeskillet").request().get();
        Assert.assertEquals(200, response.getStatus());
        String message = response.readEntity(String.class);
        Assert.assertEquals("Hello peeskillet", message);
        System.out.println(message);
    }
}

Upvotes: 2

Related Questions