如何使用 Jersey 2 测试框架为此类编写单元测试
我正在尝试为 Rest api 调用编写单元测试,该调用具有使用 Jersey2 将视频文件添加到基于 Web 的应用程序的 POST 方法.这是我要为其编写单元测试的类(TemplateController.java
)的方法的签名:
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) {
...
}
这是我的测试类的测试方法(TemplateControllerUnitTestCase.java
):
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
...
}
我能够将 AttachmentDAO
对象从测试类传递给 TemplateController
类,但无法传递在 方法中变为 null 的请求对象
.TemplateController.java 类
的(addVideoData())
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
.
我正在使用 RequestHelper
类,它是 HttpServletRequest
的帮助类,所以我想将这个类的一个对象传递给 method(addVideoData())
使用 Jersey2 测试框架.
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.
推荐答案
你可以使用Jersey 2 的 HK2 功能,有助于依赖注入.这样做,您可以创建一个 Factory
HttpServletRequest
的 code> 并从 RequestHelper
返回模拟.例如
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) {
}
}
然后在您的 JerseyTest
子类中,只需向 ResourceConfig
注册一个 AbstractBinder
.例如
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);
}
});
}
另一种选择
...根本不模拟 HttpServletRequest
,而是使用实际的 HttpServletRequest
.为此,我们需要在覆盖 getDeploymentContext()
时配置 DeploymentContext
,并返回 ServletDeploymentContext
.您可以在 此处 和 这里.第一个还有一个使用 Factory
的示例,而第二个显示了如何基于 web.xml 设置进行配置的示例.如果您选择模拟 HttpServletRequest
的情况,那么您不会需要覆盖 getTestContainerFactory
和 configureDeployment
如示例中所示.只需使用 Application configure()
覆盖就足够了,只要不依赖 servlet 功能即可.
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.
链接中的例子使用
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>${jersey.version}</version>
</dependency>
额外
我链接到的两个示例都试图利用 Sevlet 功能.因此,我将给出一个使用请求模拟的完整示例.
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
是 HttpServletRequest
的简单虚拟实现,我只覆盖一个方法 getMethod()
并始终返回 POST代码>.从结果可以看出,即使是
get
请求,它仍然返回 POST
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";
}
...
}
相关文章