package de.codecentric.mjl.jerseytest.helpers; import java.net.URI; import javax.ws.rs.core.Context; import javax.ws.rs.core.UriBuilder; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.WebResource; import com.sun.jersey.api.core.DefaultResourceConfig; import com.sun.jersey.spi.inject.SingletonTypeInjectableProvider; import com.sun.jersey.test.framework.AppDescriptor; import com.sun.jersey.test.framework.LowLevelAppDescriptor; import com.sun.jersey.test.framework.spi.container.TestContainer; import com.sun.jersey.test.framework.spi.container.TestContainerFactory; /** * An abstract JUnit 4.x-based unit test class for testing JAX-RS and Jersey-based applications * inspired by the JerseyTest class of the jersey test framework. * * LowLevelJerseyTest differs from JerseyTest in that only low-level test-containsers can be used. * Taking advantage of this restriction, LowLevelJerseyTest allows easy mocking of objects injected * via @Context and on-the-fly configuration of request- and response-filters. Another difference to * JerseyTest is, that the test-container is only started once per test-suite (and not once per * test). Although this contradicts with the rule of absolute isolation of test-cases, the * performance gain outweighs this shortcoming. * * The test-container has to be configured in methods annotated with @BeforeClass using the static * methods {@link #addClass}, {@link #addSingleton}, {@link #addFilter}, * {@link #addProviderForContext}, and so on. Note, that the test-container is initialized and start * before any @Before annotated methods are executed. So calling any of the above methods in @Before * annotated methods won't have any effect. * * The method {@link #resource()} returns a {@link WebResource}, that is already configured to point * to the root path of the test-container. * * @author Michael Lex <michael.lex@codecentric.de> */ abstract public class FastJerseyTest { private static DefaultResourceConfig resourceConfig = new DefaultResourceConfig(); private static TestContainerFactory testContainerFactory; private static TestContainer testContainer; private static Client client; public static void addClass(Class<?> resourceClass) { resourceConfig.getClasses().add(resourceClass); } public static void addSingleton(Object resourceSingleton) { resourceConfig.getSingletons().add(resourceSingleton); } public static <T> void addProviderForContext(Class<T> contextClass, T contextObject) { addSingleton(new SingletonTypeInjectableProvider<Context, T>(contextClass, contextObject) { }); } public static void addRequestFilter(Object filter) { resourceConfig.getContainerRequestFilters().add(filter); } public static void addResponseFilter(Object filter) { resourceConfig.getContainerResponseFilters().add(filter); } public static void setTestContainerFactory(TestContainerFactory newTestContainerFactory) { testContainerFactory = newTestContainerFactory; } @BeforeClass public static void cleanStaticVariables() { resourceConfig = new DefaultResourceConfig(); } public static void initServer() { AppDescriptor ad = new LowLevelAppDescriptor.Builder(resourceConfig).build(); TestContainerFactory tcf = testContainerFactory; if (tcf == null) { tcf = new FilteringInMemoryTestContainerFactory(); } testContainer = tcf.create(UriBuilder.fromUri("http://localhost/").port(9998).build(), ad); client = testContainer.getClient(); if (client == null) { client = Client.create(ad.getClientConfig()); } } public static void startServer() { if (testContainer != null) { testContainer.start(); } } @AfterClass public static void stopServer() { testContainer.stop(); testContainer = null; client = null; } public Client client() { return client; } public URI getBaseUri() { return testContainer.getBaseUri(); } public WebResource resource() { return client.resource(getBaseUri()); } @Before public void startServerBeforeFirstTestRun() { if (testContainer == null) { initServer(); startServer(); } } }