我正在构建部署在Tomcat上的Jersey Web应用程序。我很难理解如何对应用程序进行单元测试。
只需在测试中实例化这些类并对其调用方法即可测试核心业务逻辑(非Jersey资源类)(这与Jersey或Tomcat无关)。
但是,对单元球衣资源类(即映射到URL的类)进行单元测试的正确方法是什么?
我是否需要为此运行Tomcat?还是应该模拟请求和响应对象,在测试中实例化资源类,然后将模拟物提供给类?
我已经在Jersey网站上阅读了有关测试的信息,但他们在示例中使用的是Grizzly,而不是Tomcat,这是不同的。
请说明该如何完成。示例代码将受到欢迎。
如果您只想进行 _单元_测试,则无需启动任何服务器。如果您具有服务(业务层)或任何其他类似的UriInfo东西,诸如此类的东西,则可以进行模拟。Mockito是一个非常流行的模拟框架。以下是一个完整的示例
UriInfo
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")); } }
如果您要运行 _集成_测试,那么就个人而言,只要您没有在应用程序中使用特定于Tomcat的东西,我是否运行Grizzly容器与运行Tomcat容器都不会有太大区别。
使用Jersey测试框架是集成测试的不错选择,但它们没有Tomcat提供程序。只有Grizzly,In- Memory和Jetty。如果您未使用任何Servlet API,例如HttpServletRequest或ServletContext,等等,则内存中提供程序可能是可行的解决方案。这将为您提供更快的测试时间。
HttpServletRequest
ServletContext
如果 必须 使用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. * * <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")); } }