如何为Jersey Rest资源+ Grizzly + mockito编写测试用例

时间:2015-08-28 06:13:14

标签: java spring rest jersey-2.0 grizzly

我正在尝试为Jersey使用Grizzly和Mockito编写集成测试用例,Spring,我无法模拟服务类。如何模拟使用@AutoWired

在我的Resource类中注入的服务类
@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();

    }

这个测试用例正在传递,但我嘲笑的服务类没有嘲笑当代码命中该行时我得到空指针异常

1 个答案:

答案 0 :(得分:2)

所以有几个问题

  1. @Before方法。 JerseyTest已经implements a @Before method,它创建了测试容器。因此,您的模拟将不会及时创建,服务将为null。最好的办法是在configureDeployment()方法中创建服务,在那里初始化Jersey应用程序。将为每个测试用例创建一个新容器,因此每次测试都会有新的模拟。

  2. 您可以将类简单地传递给ResourceConfig构造函数,这将导致Jersey运行时创建资源类的实例。因此,在创建资源类之后,请new ResourceConfig(MyResource.class)而不是new ResourceConfig().register(resource)

  3. 因此configureDeployment()方法应该更像

    @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;
    }
    

    另一个问题是您实际上并未在请求中传递任何查询参数。因此,在您的资源方法中,参数将为null。您的请求应该更像

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

    这是一个完整的测试

    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);
        }
    }