我正在构建一个部署在Tomcat上的Jersey Web应用程序.我很难理解如何对应用进行单元测试.
通过简单地在我的测试中实例化类并调用它们上的方法(这与Jersey或Tomcat无关),可以测试核心业务逻辑(非Jersey资源类).
但是对Jersey资源类(即映射到URL的类)进行单元测试的正确方法是什么?
我需要让Tomcat运行吗?或者我应该模拟请求和响应对象,在我的测试中实例化资源类,并将模拟提供给我的类?
我已经阅读过泽西岛网站上的测试,但是他们在他们的例子中使用了Grizzly而不是Tomcat,这是不同的.
请解释一下应该怎么做.欢迎使用示例代码.
解决方法:
如果您只想进行单元测试,则无需启动任何服务器.如果你有一个服务(业务层)或任何其他注入,如UriInfo和那种性质的东西,你可以嘲笑.一个非常流行的模拟框架是Mockito.下面是一个完整的例子
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
/**
* Beside Jersey dependencies, you will need Mockito.
*
* <dependency>
* <groupId>org.mockito</groupId>
* <artifactId>mockito-core</artifactId>
* <version>1.10.19</version>
* </dependency>
*
* @author Paul Samsotha
*/
public class SomethingResourceUnitTest {
public static interface SomeService {
String getSomethingById(int id);
}
@Path("something")
public static class SomethingResource {
private final SomeService service;
@Inject
public SomethingResource(SomeService service) {
this.service = service;
}
@GET
@Path("{id}")
public Response getSomethingById(@PathParam("id") int id) {
String result = service.getSomethingById(id);
return Response.ok(result).build();
}
}
private SomethingResource resource;
private SomeService service;
@Before
public void setUp() {
service = Mockito.mock(SomeService.class);
resource = new SomethingResource(service);
}
@Test
public void testGetSomethingById() {
Mockito.when(service.getSomethingById(Mockito.anyInt())).thenReturn("Something");
Response response = resource.getSomethingById(1);
assertThat(response.getStatus(), is(200));
assertThat(response.getEntity(), instanceOf(String.class));
assertThat((String)response.getEntity(), is("Something"));
}
}
也可以看看:
> How to get instance of javax.ws.rs.core.UriInfo
如果您想运行集成测试,我个人认为,无论您是在运行Grizzly容器还是运行Tomcat容器,都没有太大区别,只要您没有在应用程序中使用特定于Tomcat的任何内容.
使用Jersey Test Framework是集成测试的一个很好的选择,但它们没有Tomcat提供程序.只有Grizzly,In-Memory和Jetty.如果您没有使用任何Servlet API,如HttpServletRequest或ServletContext等,内存提供程序可能是一个可行的解决方案.它会为您提供更快的测试时间.
也可以看看:
> junit 4 test case to test rest web service中的一些例子,除了文档中给出的例子.
如果必须使用Tomcat,则可以运行自己的嵌入式Tomcat.我没有找到太多的文档,但是有一个example in DZone.我没有真正使用嵌入式Tomcat,但是在上一个链接中的示例,你可以有类似下面的内容(已经过测试可以工作)
import java.io.File;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.Response;
import org.apache.catalina.Context;
import org.apache.catalina.startup.Tomcat;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
/**
* Aside from the Jersey dependencies, you will need the following
* Tomcat dependencies.
*
* <dependency>
* <groupId>org.apache.tomcat.embed</groupId>
* <artifactId>tomcat-embed-core</artifactId>
* <version>8.5.0</version>
* <scope>test</scope>
* </dependency>
* <dependency>
* <groupId>org.apache.tomcat.embed</groupId>
* <artifactId>tomcat-embed-logging-juli</artifactId>
* <version>8.5.0</version>
* <scope>test</scope>
* </dependency>
*
* See also https://dzone.com/articles/embedded-tomcat-minimal
*
* @author Paul Samsotha
*/
public class SomethingResourceTomcatIntegrationTest {
public static interface SomeService {
String getSomethingById(int id);
}
public static class SomeServiceImpl implements SomeService {
@Override
public String getSomethingById(int id) {
return "Something";
}
}
@Path("something")
public static class SomethingResource {
private final SomeService service;
@Inject
public SomethingResource(SomeService service) {
this.service = service;
}
@GET
@Path("{id}")
public Response getSomethingById(@PathParam("id") int id) {
String result = service.getSomethingById(id);
return Response.ok(result).build();
}
}
private Tomcat tomcat;
@Before
public void setUp() throws Exception {
tomcat = new Tomcat();
tomcat.setPort(8080);
final Context ctx = tomcat.addContext("/", new File(".").getAbsolutePath());
final ResourceConfig config = new ResourceConfig(SomethingResource.class)
.register(new AbstractBinder() {
@Override
protected void configure() {
bind(SomeServiceImpl.class).to(SomeService.class);
}
});
Tomcat.addServlet(ctx, "jersey-test", new ServletContainer(config));
ctx.addServletMapping("/*", "jersey-test");
tomcat.start();
}
@After
public void tearDown() throws Exception {
tomcat.stop();
}
@Test
public void testGetSomethingById() {
final String baseUri = "http://localhost:8080";
final Response response = ClientBuilder.newClient()
.target(baseUri).path("something").path("1")
.request().get();
assertThat(response.getStatus(), is(200));
assertThat(response.readEntity(String.class), is("Something"));
}
}