如何使用Jersey 2测试框架为此类编写单元测试

时间:2015-02-23 09:37:56

标签: java unit-testing rest jersey jersey-2.0

我正在尝试为Rest api调用编写单元测试,该调用具有POST方法,用于使用Jersey2将视频文件添加到基于Web的应用程序。这是我的类(TemplateController.java)方法的签名,我想为其编写单元测试:

@POST
@Path("/video/add")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response addVideoData(
    @Context HttpServletRequest request, 
    AttachmentDTO attachmentDTO) {
        ...
}

以下是我的测试类(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
    ...
}

我能够将AttachmentDAO对象从测试类传递给TemplateController类,但无法传递method(addVideoData()) TemplateController.java class中变为null的请求对象{1}}。

我使用的RequestHelper类是HttpServletRequest的辅助类,所以我想使用Jersey2测试框架将此类的对象传递给method(addVideoData())。< / p>

1 个答案:

答案 0 :(得分:11)

您可以使用泽西2的HK2功能,这有助于Dependency Injection。这样做,您可以为HttpServletRequest创建Factory并从RequestHelper返回模拟。例如

public class HttpServletRequestFactory implements Factory<HttpServlet> {

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

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

然后在JerseyTest子类中,只需使用AbstractBinder注册ResourceConfig即可。例如

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

另一个选项

...根本不是模仿HttpServletRequest,而是使用实际的HttpServletRequest。为此,我们需要在覆盖DeploymentContext时配置getDeploymentContext(),并返回ServletDeploymentContext。您可以看到示例herehere。第一个还有一个使用Factory的示例,而第二个示例显示了如何基于web.xml设置进行配置。如果您选择用于模拟HttpServletRequest的案例,则不会需要覆盖getTestContainerFactoryconfigureDeployment,如示例中所示。只要使用Application configure()覆盖就足够了,只要没有别的东西依赖于servlet功能。

链接中的示例使用

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

附加

我链接的示例都试图利用Sevlet功能。所以我将给出一个使用请求模拟的完整示例。

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很简单,是HttpServletRequest的虚拟实现,我只覆盖一个方法getMethod()并始终返回POST。您可以从结果中看到,即使它是get请求,它仍会返回POST

public class MockHttpServletRequest implements HttpServletRequest {

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