简体   繁体   中英

How can I unit-test a Jersey web application deployed on Tomcat?

I'm building a Jersey web application deployed on Tomcat. I'm having a hard time understanding how to unit test the app.

Testing the core business logic (the non-Jersey-resource classes) is possible by simply instantiating the classes in my tests and calling methods on them (this has nothing to do with Jersey or Tomcat).

But what is the right way to unit test the Jersey resource classes (ie, the classes that map to URLs)?

Do I need to have Tomcat running for this? Or should I mock the request and response objects, instantiate the resource classes in my tests, and feed the mocks to my classes?

I have read about testing in Jersey's site, but they're using Grizzly and not Tomcat in their examples, which is different.

Please explain how this should be done. Example code would be welcome.

If you just want to unit test, there's no need to start any server. If you have an services (business layer) or any other injections like UriInfo and things of that nature, you can just mock the. A pretty popular mocking framework is Mockito . Below is a complete example

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"));
    }
}

See Also:


If you want to run an integration test, personally I don't see much difference whether or not you are running a Grizzly container vs. running a Tomcat container, as long as you are not using anything specific to Tomcat in your application.

Using the Jersey Test Framework is a good option for integration testing, but they do not have a Tomcat provider. There is only Grizzly, In-Memory and Jetty. If you are not using any Servlet APIs like HttpServletRequest or ServletContext , etc, the In-Memory provider may be a viable solution. It will give you quicker test time.

See Also:


If you must use Tomcat, you can run your own embedded Tomcat. I have not found much documentation, but there is an example in DZone . I don't really use the embedded Tomcat, but going of the example in the previous link, you can have something like the following (which has been tested to work)

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"));
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM