如何对Tomcat上部署的Jersey Web应用程序进行unit testing?

我正在构建一个部署在Tomcat上的Jersey Web应用程序。 我很难理解如何对应用进行unit testing。

通过简单地在我的测试中实例化类并调用它们上的方法(这与Jersey或Tomcat无关),可以测试核心业务逻辑(非Jersey资源类)。

但是对Jersey资源类(即映射到URL的类)进行unit testing的正确方法是什么?

我需要让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. * *  * org.mockito * mockito-core * 1.10.19 *  * * @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")); } } 

也可以看看:

  • 如何获取javax.ws.rs.core.UriInfo的实例

如果您想运行集成测试,我个人认为您运行Grizzly容器与运行Tomcat容器之间没有太大区别,只要您没有在应用程序中使用特定于Tomcat的任何内容。

使用Jersey Test Framework是集成测试的一个很好的选择,但它们没有Tomcat提供程序。 只有Grizzly,In-Memory和Jetty。 如果您没有使用任何Servlet API,如HttpServletRequestServletContext等,内存提供程序可能是一个可行的解决方案。 它会为您提供更快的测试时间。

也可以看看:

  • junit 4测试用例测试其余Web服务的一些例子,除了文档中给出的例子。

如果必须使用Tomcat,则可以运行自己的嵌入式Tomcat。 我没有找到太多的文档,但在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. * *  * org.apache.tomcat.embed * tomcat-embed-core * 8.5.0 * test *  *  * org.apache.tomcat.embed * tomcat-embed-logging-juli * 8.5.0 * test *  * * 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")); } }