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

标签 java unit-testing rest jersey jersey-2.0

我正在尝试为 Rest api 调用编写单元测试,该调用具有使用 Jersey2 将视频文件添加到基于 Web 的应用程序的 POST 方法。这是我要为其编写单元测试的类 (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 类,但无法传递在 方法中变为 null 的请求对象TemplateController.java 类的(addVideoData())

我正在使用 RequestHelper 类,它是 HttpServletRequest 的辅助类,所以我想将此类的一个对象传递给 方法(addVideoData( )) 使用 Jersey2 测试框架。

最佳答案

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

public class HttpServletRequestFactory implements Factory<HttpServlet> {

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

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

然后在您的 JerseyTest 子类中,只需使用 ResourceConfig 注册一个 AbstractBinder。例如

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

另一种选择

...根本不模拟 HttpServletRequest,而是使用实际的 HttpServletRequest。为此,我们需要在覆盖 getDeploymentContext() 时配置 DeploymentContext,并返回 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);
    }
}

MockHttpServletRequestHttpServletRequest 的一个简单的虚拟实现,我只重写一个方法 getMethod() 并且总是返回 POST。从结果可以看出,虽然是get请求,但是还是返回了POST

public class MockHttpServletRequest implements HttpServletRequest {

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

关于java - 如何使用 Jersey 2 测试框架为此类编写单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28670665/

相关文章:

swift - 在 Swift 中如何测试索引是否超出范围?

java - 如何在 Neo4j 非托管扩展中进行压缩响应?

C# - 以字节 block 的形式从 Google Drive 下载

rest - Go Gorilla Mux 没有按预期路由

java - 如何配置 Maven 阴影插件以在我的 jar 中包含测试代码?

java - 如何在Java中批量执行一组 'select count(*)'查询?

Java AWT/SWT/Swing : How to plan a GUI?

unit-testing - 如何为特定类自定义 AutoFixture 行为

c# - 程序集中的所有 NUnit 测试都会被跳过,因为我在引用的项目中添加了空参数检查

java - 如何验证 json 模式中的 UUID 属性字段?