├── README ├── mjl-jersey-build └── pom.xml ├── mjl-jersey-client ├── pom.xml └── src │ └── main │ └── java │ └── de │ └── codecentric │ └── mjl │ └── jerseytest │ └── client │ └── TodoClient.java ├── mjl-jersey-common ├── pom.xml └── src │ └── main │ ├── java │ └── de │ │ └── codecentric │ │ └── mjl │ │ └── jerseytest │ │ └── exceptions │ │ └── TodoNotFoundException.java │ └── webapp │ └── WEB-INF │ └── web.xml └── mjl-jersey-server ├── pom.xml └── src ├── main ├── java │ └── de │ │ └── codecentric │ │ └── mjl │ │ └── jerseytest │ │ ├── providers │ │ ├── NotFoundMapper.java │ │ └── TodoServiceProvider.java │ │ ├── resources │ │ └── TodoResource.java │ │ └── services │ │ └── TodoService.java └── webapp │ └── WEB-INF │ └── web.xml └── test └── java └── de └── codecentric └── mjl └── jerseytest ├── FastTodoResourceTest.java ├── TodoResourceTest.java ├── TodoResourceWithLowLevelContainer.java └── helpers ├── FastJerseyTest.java └── FilteringInMemoryTestContainerFactory.java /README: -------------------------------------------------------------------------------- 1 | Writing lightweight REST integration tests with the Jersey Test Framework 2 | 3 | To compile the project, simply run "mvn package" inside the mjl-jersey-build directory. To view the project in eclipse, best use the maven eclipse plugin ("mvn eclipse:eclipse") and import as existing project. 4 | 5 | There is a blog post corresponding to this mini-tutorial: http://mjlex.blogspot.de/2012/04/writing-lightweight-rest-integration.html. -------------------------------------------------------------------------------- /mjl-jersey-build/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | de.codecentric.mjl 7 | mjl-jersey-build 8 | mjl-jersey-build 9 | pom 10 | 1.0.0-SNAPSHOT 11 | 12 | 13 | 1.6 14 | 1.12 15 | 1.5.10 16 | 17 | 18 | 19 | ../mjl-jersey-client/ 20 | ../mjl-jersey-server/ 21 | ../mjl-jersey-common/ 22 | 23 | 24 | 25 | 26 | 27 | org.apache.commons 28 | commons-lang3 29 | 3.0 30 | 31 | 32 | 33 | com.sun.jersey 34 | jersey-server 35 | ${jersey-version} 36 | 37 | 38 | com.sun.jersey.contribs 39 | jersey-multipart 40 | ${jersey-version} 41 | 42 | 43 | com.sun.jersey 44 | jersey-json 45 | ${jersey-version} 46 | 47 | 48 | com.sun.jersey 49 | jersey-client 50 | ${jersey-version} 51 | 52 | 53 | com.sun.jersey 54 | jersey-core 55 | ${jersey-version} 56 | 57 | 58 | com.sun.jersey 59 | jersey-servlet 60 | ${jersey-version} 61 | 62 | 63 | com.sun.jersey.jersey-test-framework 64 | jersey-test-framework-inmemory 65 | ${jersey-version} 66 | test 67 | 68 | 69 | com.sun.jersey.jersey-test-framework 70 | jersey-test-framework-grizzly2 71 | ${jersey-version} 72 | test 73 | 74 | 75 | 76 | 77 | org.mockito 78 | mockito-core 79 | 1.9.0 80 | test 81 | 82 | 83 | junit 84 | junit 85 | 4.8.2 86 | test 87 | 88 | 89 | org.hamcrest 90 | hamcrest-core 91 | 1.1 92 | test 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | org.apache.maven.plugins 101 | maven-compiler-plugin 102 | 103 | ${java-version} 104 | ${java-version} 105 | 106 | 107 | 108 | org.apache.maven.plugins 109 | maven-eclipse-plugin 110 | 2.8 111 | 112 | 2.0 113 | 114 | 115 | 116 | org.apache.maven.plugins 117 | maven-dependency-plugin 118 | 119 | 120 | install 121 | install 122 | 123 | sources 124 | 125 | 126 | 127 | 128 | 129 | org.apache.maven.plugins 130 | maven-site-plugin 131 | 3.0 132 | 133 | ../site 134 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /mjl-jersey-client/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | de.codecentric.mjl 5 | mjl-jersey-client 6 | 1.0.0-SNAPSHOT 7 | mjl-jersey-client 8 | 9 | de.codecentric.mjl 10 | mjl-jersey-build 11 | 1.0.0-SNAPSHOT 12 | ../mjl-jersey-build 13 | 14 | 15 | 16 | de.codecentric.mjl 17 | mjl-jersey-common 18 | 1.0.0-SNAPSHOT 19 | 20 | 21 | org.apache.commons 22 | commons-lang3 23 | 24 | 25 | com.sun.jersey 26 | jersey-server 27 | 28 | 29 | com.sun.jersey.contribs 30 | jersey-multipart 31 | 32 | 33 | com.sun.jersey 34 | jersey-json 35 | 36 | 37 | com.sun.jersey 38 | jersey-client 39 | 40 | 41 | com.sun.jersey 42 | jersey-core 43 | 44 | 45 | com.sun.jersey 46 | jersey-servlet 47 | 48 | 49 | com.sun.jersey.jersey-test-framework 50 | jersey-test-framework-inmemory 51 | test 52 | 53 | 54 | com.sun.jersey.jersey-test-framework 55 | jersey-test-framework-grizzly2 56 | test 57 | 58 | 59 | junit 60 | junit 61 | test 62 | 63 | 64 | org.mockito 65 | mockito-core 66 | test 67 | 68 | 69 | org.hamcrest 70 | hamcrest-core 71 | test 72 | 73 | 74 | -------------------------------------------------------------------------------- /mjl-jersey-client/src/main/java/de/codecentric/mjl/jerseytest/client/TodoClient.java: -------------------------------------------------------------------------------- 1 | package de.codecentric.mjl.jerseytest.client; 2 | 3 | import com.sun.jersey.api.client.Client; 4 | import com.sun.jersey.api.client.ClientResponse.Status; 5 | import com.sun.jersey.api.client.UniformInterfaceException; 6 | import com.sun.jersey.api.client.WebResource; 7 | 8 | import de.codecentric.mjl.jerseytest.exceptions.TodoNotFoundException; 9 | 10 | public class TodoClient { 11 | 12 | public static final String TODO_RESOURCE_PATH = "/todo"; 13 | 14 | private final String uri; 15 | 16 | private final Client client = new Client(); 17 | 18 | public TodoClient(String uri) { 19 | this.uri = uri; 20 | } 21 | 22 | public WebResource resource() { 23 | return client.resource(uri).path(TODO_RESOURCE_PATH); 24 | } 25 | 26 | public WebResource resource(String todo) { 27 | return resource().path("/" + todo); 28 | } 29 | 30 | public String getAllTodos() { 31 | String todos = resource().get(String.class); 32 | return todos; 33 | } 34 | 35 | public void addTodo(String todoToAdd) { 36 | resource().post(todoToAdd); 37 | } 38 | 39 | public void removeTodo(String todoToRemove) { 40 | try { 41 | resource(todoToRemove).delete(); 42 | } catch (UniformInterfaceException e) { 43 | if (e.getResponse().getClientResponseStatus() == Status.BAD_REQUEST 44 | && "TodoNotFoundException".equals(e.getResponse().getEntity(String.class))) { 45 | throw new TodoNotFoundException("Todo '" + todoToRemove + "' not found"); 46 | } else { 47 | throw e; 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /mjl-jersey-common/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | de.codecentric.mjl 5 | mjl-jersey-common 6 | 1.0.0-SNAPSHOT 7 | mjl-jersey-common 8 | 9 | de.codecentric.mjl 10 | mjl-jersey-build 11 | 1.0.0-SNAPSHOT 12 | ../mjl-jersey-build 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /mjl-jersey-common/src/main/java/de/codecentric/mjl/jerseytest/exceptions/TodoNotFoundException.java: -------------------------------------------------------------------------------- 1 | package de.codecentric.mjl.jerseytest.exceptions; 2 | 3 | public class TodoNotFoundException extends RuntimeException { 4 | public TodoNotFoundException() { 5 | super(); 6 | } 7 | 8 | public TodoNotFoundException(String msg) { 9 | super(msg); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /mjl-jersey-common/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Jersey Web Application 7 | com.sun.jersey.spi.container.servlet.ServletContainer 8 | 9 | com.sun.jersey.config.property.packages 10 | de.codecentric.mjl 11 | 12 | 1 13 | 14 | 15 | Jersey Web Application 16 | /webresources/* 17 | 18 | 19 | -------------------------------------------------------------------------------- /mjl-jersey-server/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | de.codecentric.mjl 5 | mjl-jersey-server 6 | war 7 | 1.0.0-SNAPSHOT 8 | mjl-jersey-server 9 | 10 | de.codecentric.mjl 11 | mjl-jersey-build 12 | 1.0.0-SNAPSHOT 13 | ../mjl-jersey-build 14 | 15 | 16 | 17 | de.codecentric.mjl 18 | mjl-jersey-common 19 | 1.0.0-SNAPSHOT 20 | 21 | 22 | org.apache.commons 23 | commons-lang3 24 | 25 | 26 | com.sun.jersey 27 | jersey-server 28 | 29 | 30 | com.sun.jersey.contribs 31 | jersey-multipart 32 | 33 | 34 | com.sun.jersey 35 | jersey-json 36 | 37 | 38 | com.sun.jersey 39 | jersey-client 40 | 41 | 42 | com.sun.jersey 43 | jersey-core 44 | 45 | 46 | com.sun.jersey 47 | jersey-servlet 48 | 49 | 50 | com.sun.jersey.jersey-test-framework 51 | jersey-test-framework-inmemory 52 | test 53 | 54 | 55 | com.sun.jersey.jersey-test-framework 56 | jersey-test-framework-grizzly2 57 | test 58 | 59 | 60 | junit 61 | junit 62 | test 63 | 64 | 65 | org.mockito 66 | mockito-core 67 | 1.8.5 68 | test 69 | 70 | 71 | de.codecentric.mjl 72 | mjl-jersey-client 73 | 1.0.0-SNAPSHOT 74 | test 75 | 76 | 77 | -------------------------------------------------------------------------------- /mjl-jersey-server/src/main/java/de/codecentric/mjl/jerseytest/providers/NotFoundMapper.java: -------------------------------------------------------------------------------- 1 | package de.codecentric.mjl.jerseytest.providers; 2 | 3 | import javax.ws.rs.core.Response; 4 | import javax.ws.rs.ext.ExceptionMapper; 5 | import javax.ws.rs.ext.Provider; 6 | 7 | import de.codecentric.mjl.jerseytest.exceptions.TodoNotFoundException; 8 | 9 | @Provider 10 | public class NotFoundMapper implements ExceptionMapper { 11 | @Override 12 | public Response toResponse(TodoNotFoundException e) { 13 | return Response.status(Response.Status.BAD_REQUEST).entity("TodoNotFoundException").build(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /mjl-jersey-server/src/main/java/de/codecentric/mjl/jerseytest/providers/TodoServiceProvider.java: -------------------------------------------------------------------------------- 1 | package de.codecentric.mjl.jerseytest.providers; 2 | 3 | import javax.ws.rs.core.Context; 4 | import javax.ws.rs.ext.Provider; 5 | 6 | import com.sun.jersey.spi.inject.SingletonTypeInjectableProvider; 7 | 8 | import de.codecentric.mjl.jerseytest.services.TodoService; 9 | 10 | @Provider 11 | public class TodoServiceProvider extends SingletonTypeInjectableProvider { 12 | 13 | public TodoServiceProvider() { 14 | super(TodoService.class, new TodoService()); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /mjl-jersey-server/src/main/java/de/codecentric/mjl/jerseytest/resources/TodoResource.java: -------------------------------------------------------------------------------- 1 | package de.codecentric.mjl.jerseytest.resources; 2 | 3 | import javax.ws.rs.Consumes; 4 | import javax.ws.rs.DELETE; 5 | import javax.ws.rs.GET; 6 | import javax.ws.rs.POST; 7 | import javax.ws.rs.Path; 8 | import javax.ws.rs.PathParam; 9 | import javax.ws.rs.Produces; 10 | import javax.ws.rs.core.Context; 11 | 12 | import org.apache.commons.lang3.StringUtils; 13 | 14 | import de.codecentric.mjl.jerseytest.services.TodoService; 15 | 16 | /** 17 | * Example resource class hosted at the URI path "/myresource" 18 | */ 19 | @Path("/todo") 20 | public class TodoResource { 21 | 22 | @Context 23 | private TodoService todoService; 24 | 25 | @GET 26 | @Produces("text/plain") 27 | public String getTodos() { 28 | return StringUtils.join(todoService.getAllTodos(), ","); 29 | } 30 | 31 | @POST 32 | @Consumes("text/plain") 33 | public void addTodo(String newTodo) { 34 | todoService.addTodo(newTodo); 35 | } 36 | 37 | @DELETE 38 | @Path("/{todo}") 39 | public void removeTodo(@PathParam("todo") String todoToRemove) { 40 | todoService.removeTodo(todoToRemove); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /mjl-jersey-server/src/main/java/de/codecentric/mjl/jerseytest/services/TodoService.java: -------------------------------------------------------------------------------- 1 | package de.codecentric.mjl.jerseytest.services; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import de.codecentric.mjl.jerseytest.exceptions.TodoNotFoundException; 7 | 8 | public class TodoService { 9 | 10 | List todos = new ArrayList(); 11 | 12 | public List getAllTodos() { 13 | return new ArrayList(todos); 14 | } 15 | 16 | public void addTodo(String todo) { 17 | todos.add(todo); 18 | } 19 | 20 | public void removeTodo(String todo) { 21 | if (todos.remove(todo) == false) { 22 | throw new TodoNotFoundException("Todo '" + todo + "' not found."); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /mjl-jersey-server/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Jersey Web Application 7 | com.sun.jersey.spi.container.servlet.ServletContainer 8 | 9 | com.sun.jersey.config.property.packages 10 | de.codecentric.mjl 11 | 12 | 1 13 | 14 | 15 | Jersey Web Application 16 | /* 17 | 18 | 19 | -------------------------------------------------------------------------------- /mjl-jersey-server/src/test/java/de/codecentric/mjl/jerseytest/FastTodoResourceTest.java: -------------------------------------------------------------------------------- 1 | package de.codecentric.mjl.jerseytest; 2 | 3 | import javax.ws.rs.core.Context; 4 | import javax.ws.rs.ext.Provider; 5 | 6 | import org.junit.Assert; 7 | import org.junit.Before; 8 | import org.junit.BeforeClass; 9 | import org.junit.Test; 10 | import org.mockito.Mockito; 11 | import org.mockito.internal.util.reflection.Whitebox; 12 | 13 | import com.sun.jersey.api.client.ClientResponse; 14 | import com.sun.jersey.api.client.ClientResponse.Status; 15 | import com.sun.jersey.spi.inject.SingletonTypeInjectableProvider; 16 | 17 | import de.codecentric.mjl.jerseytest.client.TodoClient; 18 | import de.codecentric.mjl.jerseytest.exceptions.TodoNotFoundException; 19 | import de.codecentric.mjl.jerseytest.helpers.FastJerseyTest; 20 | import de.codecentric.mjl.jerseytest.helpers.FilteringInMemoryTestContainerFactory; 21 | import de.codecentric.mjl.jerseytest.providers.NotFoundMapper; 22 | import de.codecentric.mjl.jerseytest.resources.TodoResource; 23 | import de.codecentric.mjl.jerseytest.services.TodoService; 24 | 25 | public class FastTodoResourceTest extends FastJerseyTest { 26 | 27 | public static TodoService todoServiceMock = Mockito.mock(TodoService.class); 28 | 29 | @BeforeClass 30 | public static void configure() { 31 | addClass(TodoResource.class); 32 | addClass(NotFoundMapper.class); 33 | addProviderForContext(TodoService.class, todoServiceMock); 34 | setTestContainerFactory(new FilteringInMemoryTestContainerFactory()); 35 | } 36 | 37 | @Before 38 | public void resetMocks() { 39 | // the mock is stored in a static field and must be reset manually before each test 40 | Mockito.reset(todoServiceMock); 41 | } 42 | 43 | @Test(expected = TodoNotFoundException.class) 44 | public void removeTodoShouldThrowNotFoundException() { 45 | final String todo = "test-todo"; 46 | Mockito.doThrow(new TodoNotFoundException()).when(todoServiceMock).removeTodo(todo); 47 | todoClient().removeTodo(todo); 48 | } 49 | 50 | @Test 51 | public void shouldReturn400OnNotFoundException() { 52 | String todo = "test-todo"; 53 | Mockito.doThrow(new TodoNotFoundException()).when(todoServiceMock).removeTodo(todo); 54 | ClientResponse response = resource().path("todo/" + todo).delete(ClientResponse.class); 55 | Assert.assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus()); 56 | Assert.assertEquals("TodoNotFoundException", response.getEntity(String.class)); 57 | } 58 | 59 | private TodoClient todoClient() { 60 | TodoClient todoClient = new TodoClient(getBaseUri().toString()); 61 | Whitebox.setInternalState(todoClient, "client", client()); 62 | return todoClient; 63 | } 64 | 65 | @Provider 66 | public static class MockTodoServiceProvider extends 67 | SingletonTypeInjectableProvider { 68 | 69 | public MockTodoServiceProvider() { 70 | super(TodoService.class, todoServiceMock); 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /mjl-jersey-server/src/test/java/de/codecentric/mjl/jerseytest/TodoResourceTest.java: -------------------------------------------------------------------------------- 1 | package de.codecentric.mjl.jerseytest; 2 | 3 | import javax.ws.rs.core.Context; 4 | import javax.ws.rs.ext.Provider; 5 | 6 | import org.junit.Assert; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | import org.mockito.Mockito; 10 | import org.mockito.internal.util.reflection.Whitebox; 11 | 12 | import com.sun.jersey.api.client.ClientResponse; 13 | import com.sun.jersey.api.client.ClientResponse.Status; 14 | import com.sun.jersey.api.core.ClassNamesResourceConfig; 15 | import com.sun.jersey.spi.container.servlet.WebComponent; 16 | import com.sun.jersey.spi.inject.SingletonTypeInjectableProvider; 17 | import com.sun.jersey.test.framework.JerseyTest; 18 | import com.sun.jersey.test.framework.WebAppDescriptor; 19 | import com.sun.jersey.test.framework.spi.container.TestContainerFactory; 20 | import com.sun.jersey.test.framework.spi.container.grizzly2.web.GrizzlyWebTestContainerFactory; 21 | 22 | import de.codecentric.mjl.jerseytest.client.TodoClient; 23 | import de.codecentric.mjl.jerseytest.exceptions.TodoNotFoundException; 24 | import de.codecentric.mjl.jerseytest.providers.NotFoundMapper; 25 | import de.codecentric.mjl.jerseytest.resources.TodoResource; 26 | import de.codecentric.mjl.jerseytest.services.TodoService; 27 | 28 | public class TodoResourceTest extends JerseyTest { 29 | 30 | public static TodoService todoServiceMock = Mockito.mock(TodoService.class); 31 | 32 | @Override 33 | public WebAppDescriptor configure() { 34 | return new WebAppDescriptor.Builder() 35 | .initParam(WebComponent.RESOURCE_CONFIG_CLASS, 36 | ClassNamesResourceConfig.class.getName()) 37 | .initParam( 38 | ClassNamesResourceConfig.PROPERTY_CLASSNAMES, 39 | TodoResource.class.getName() + ";" 40 | + MockTodoServiceProvider.class.getName() + ";" 41 | + NotFoundMapper.class.getName()).build(); 42 | } 43 | 44 | @Override 45 | public TestContainerFactory getTestContainerFactory() { 46 | return new GrizzlyWebTestContainerFactory(); 47 | } 48 | 49 | @Before 50 | public void resetMocks() { 51 | // the mock is stored in a static field and must be reset manually before each test 52 | Mockito.reset(todoServiceMock); 53 | } 54 | 55 | @Test(expected = TodoNotFoundException.class) 56 | public void removeTodoShouldThrowNotFoundException() { 57 | final String todo = "test-todo"; 58 | Mockito.doThrow(new TodoNotFoundException()).when(todoServiceMock).removeTodo(todo); 59 | todoClient().removeTodo(todo); 60 | } 61 | 62 | @Test 63 | public void shouldReturn400OnNotFoundException() { 64 | String todo = "test-todo"; 65 | Mockito.doThrow(new TodoNotFoundException()).when(todoServiceMock).removeTodo(todo); 66 | ClientResponse response = resource().path("todo/" + todo).delete(ClientResponse.class); 67 | Assert.assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus()); 68 | Assert.assertEquals("TodoNotFoundException", response.getEntity(String.class)); 69 | } 70 | 71 | private TodoClient todoClient() { 72 | TodoClient todoClient = new TodoClient(getBaseURI().toString()); 73 | Whitebox.setInternalState(todoClient, "client", client()); 74 | return todoClient; 75 | } 76 | 77 | @Provider 78 | public static class MockTodoServiceProvider extends 79 | SingletonTypeInjectableProvider { 80 | 81 | public MockTodoServiceProvider() { 82 | super(TodoService.class, todoServiceMock); 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /mjl-jersey-server/src/test/java/de/codecentric/mjl/jerseytest/TodoResourceWithLowLevelContainer.java: -------------------------------------------------------------------------------- 1 | package de.codecentric.mjl.jerseytest; 2 | 3 | import javax.ws.rs.core.Context; 4 | 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | import org.mockito.Mockito; 8 | import org.mockito.internal.util.reflection.Whitebox; 9 | 10 | import com.sun.jersey.api.core.DefaultResourceConfig; 11 | import com.sun.jersey.spi.inject.SingletonTypeInjectableProvider; 12 | import com.sun.jersey.test.framework.JerseyTest; 13 | import com.sun.jersey.test.framework.LowLevelAppDescriptor; 14 | import com.sun.jersey.test.framework.spi.container.TestContainerFactory; 15 | import com.sun.jersey.test.framework.spi.container.grizzly2.GrizzlyTestContainerFactory; 16 | 17 | import de.codecentric.mjl.jerseytest.client.TodoClient; 18 | import de.codecentric.mjl.jerseytest.exceptions.TodoNotFoundException; 19 | import de.codecentric.mjl.jerseytest.providers.NotFoundMapper; 20 | import de.codecentric.mjl.jerseytest.resources.TodoResource; 21 | import de.codecentric.mjl.jerseytest.services.TodoService; 22 | 23 | public class TodoResourceWithLowLevelContainer extends JerseyTest { 24 | 25 | public static TodoService todoServiceMock = Mockito.mock(TodoService.class); 26 | 27 | @Override 28 | public LowLevelAppDescriptor configure() { 29 | DefaultResourceConfig resourceConfig = new DefaultResourceConfig(); 30 | resourceConfig.getSingletons().add( 31 | new SingletonTypeInjectableProvider(TodoService.class, 32 | todoServiceMock) { 33 | }); 34 | resourceConfig.getClasses().add(NotFoundMapper.class); 35 | resourceConfig.getClasses().add(TodoResource.class); 36 | return new LowLevelAppDescriptor.Builder(resourceConfig).build(); 37 | } 38 | 39 | @Override 40 | public TestContainerFactory getTestContainerFactory() { 41 | return new GrizzlyTestContainerFactory(); 42 | } 43 | 44 | @Before 45 | public void resetMocks() { 46 | // the mock is stored in a static field and must be reset manually before each test 47 | Mockito.reset(todoServiceMock); 48 | } 49 | 50 | @Test(expected = TodoNotFoundException.class) 51 | public void removeTodoShouldThrowNotFoundException() { 52 | final String todo = "test-todo"; 53 | Mockito.doThrow(new TodoNotFoundException()).when(todoServiceMock).removeTodo(todo); 54 | todoClient().removeTodo(todo); 55 | } 56 | 57 | private TodoClient todoClient() { 58 | TodoClient todoClient = new TodoClient(getBaseURI().toString()); 59 | Whitebox.setInternalState(todoClient, "client", client()); 60 | return todoClient; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /mjl-jersey-server/src/test/java/de/codecentric/mjl/jerseytest/helpers/FastJerseyTest.java: -------------------------------------------------------------------------------- 1 | package de.codecentric.mjl.jerseytest.helpers; 2 | 3 | import java.net.URI; 4 | 5 | import javax.ws.rs.core.Context; 6 | import javax.ws.rs.core.UriBuilder; 7 | 8 | import org.junit.AfterClass; 9 | import org.junit.Before; 10 | import org.junit.BeforeClass; 11 | 12 | import com.sun.jersey.api.client.Client; 13 | import com.sun.jersey.api.client.WebResource; 14 | import com.sun.jersey.api.core.DefaultResourceConfig; 15 | import com.sun.jersey.spi.inject.SingletonTypeInjectableProvider; 16 | import com.sun.jersey.test.framework.AppDescriptor; 17 | import com.sun.jersey.test.framework.LowLevelAppDescriptor; 18 | import com.sun.jersey.test.framework.spi.container.TestContainer; 19 | import com.sun.jersey.test.framework.spi.container.TestContainerFactory; 20 | 21 | /** 22 | * An abstract JUnit 4.x-based unit test class for testing JAX-RS and Jersey-based applications 23 | * inspired by the JerseyTest class of the jersey test framework. 24 | * 25 | * LowLevelJerseyTest differs from JerseyTest in that only low-level test-containsers can be used. 26 | * Taking advantage of this restriction, LowLevelJerseyTest allows easy mocking of objects injected 27 | * via @Context and on-the-fly configuration of request- and response-filters. Another difference to 28 | * JerseyTest is, that the test-container is only started once per test-suite (and not once per 29 | * test). Although this contradicts with the rule of absolute isolation of test-cases, the 30 | * performance gain outweighs this shortcoming. 31 | * 32 | * The test-container has to be configured in methods annotated with @BeforeClass using the static 33 | * methods {@link #addClass}, {@link #addSingleton}, {@link #addFilter}, 34 | * {@link #addProviderForContext}, and so on. Note, that the test-container is initialized and start 35 | * before any @Before annotated methods are executed. So calling any of the above methods in @Before 36 | * annotated methods won't have any effect. 37 | * 38 | * The method {@link #resource()} returns a {@link WebResource}, that is already configured to point 39 | * to the root path of the test-container. 40 | * 41 | * @author Michael Lex 42 | */ 43 | abstract public class FastJerseyTest { 44 | 45 | private static DefaultResourceConfig resourceConfig = new DefaultResourceConfig(); 46 | 47 | private static TestContainerFactory testContainerFactory; 48 | 49 | private static TestContainer testContainer; 50 | 51 | private static Client client; 52 | 53 | public static void addClass(Class resourceClass) { 54 | resourceConfig.getClasses().add(resourceClass); 55 | } 56 | 57 | public static void addSingleton(Object resourceSingleton) { 58 | resourceConfig.getSingletons().add(resourceSingleton); 59 | } 60 | 61 | public static void addProviderForContext(Class contextClass, T contextObject) { 62 | addSingleton(new SingletonTypeInjectableProvider(contextClass, contextObject) { 63 | }); 64 | } 65 | 66 | public static void addRequestFilter(Object filter) { 67 | resourceConfig.getContainerRequestFilters().add(filter); 68 | } 69 | 70 | public static void addResponseFilter(Object filter) { 71 | resourceConfig.getContainerResponseFilters().add(filter); 72 | } 73 | 74 | public static void setTestContainerFactory(TestContainerFactory newTestContainerFactory) { 75 | testContainerFactory = newTestContainerFactory; 76 | } 77 | 78 | @BeforeClass 79 | public static void cleanStaticVariables() { 80 | resourceConfig = new DefaultResourceConfig(); 81 | } 82 | 83 | public static void initServer() { 84 | AppDescriptor ad = new LowLevelAppDescriptor.Builder(resourceConfig).build(); 85 | TestContainerFactory tcf = testContainerFactory; 86 | if (tcf == null) { 87 | tcf = new FilteringInMemoryTestContainerFactory(); 88 | } 89 | testContainer = tcf.create(UriBuilder.fromUri("http://localhost/").port(9998).build(), ad); 90 | client = testContainer.getClient(); 91 | if (client == null) { 92 | client = Client.create(ad.getClientConfig()); 93 | } 94 | } 95 | 96 | public static void startServer() { 97 | if (testContainer != null) { 98 | testContainer.start(); 99 | } 100 | } 101 | 102 | @AfterClass 103 | public static void stopServer() { 104 | testContainer.stop(); 105 | testContainer = null; 106 | client = null; 107 | } 108 | 109 | public Client client() { 110 | return client; 111 | } 112 | 113 | public URI getBaseUri() { 114 | return testContainer.getBaseUri(); 115 | } 116 | 117 | public WebResource resource() { 118 | return client.resource(getBaseUri()); 119 | } 120 | 121 | @Before 122 | public void startServerBeforeFirstTestRun() { 123 | if (testContainer == null) { 124 | initServer(); 125 | startServer(); 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /mjl-jersey-server/src/test/java/de/codecentric/mjl/jerseytest/helpers/FilteringInMemoryTestContainerFactory.java: -------------------------------------------------------------------------------- 1 | package de.codecentric.mjl.jerseytest.helpers; 2 | 3 | import java.net.URI; 4 | import java.util.Set; 5 | import java.util.logging.Logger; 6 | 7 | import javax.ws.rs.core.UriBuilder; 8 | 9 | import com.sun.jersey.api.client.Client; 10 | import com.sun.jersey.api.client.config.ClientConfig; 11 | import com.sun.jersey.api.client.config.DefaultClientConfig; 12 | import com.sun.jersey.api.core.ResourceConfig; 13 | import com.sun.jersey.spi.container.WebApplication; 14 | import com.sun.jersey.spi.container.WebApplicationFactory; 15 | import com.sun.jersey.test.framework.AppDescriptor; 16 | import com.sun.jersey.test.framework.LowLevelAppDescriptor; 17 | import com.sun.jersey.test.framework.impl.container.inmemory.TestResourceClientHandler; 18 | import com.sun.jersey.test.framework.spi.container.TestContainer; 19 | import com.sun.jersey.test.framework.spi.container.TestContainerFactory; 20 | import com.sun.jersey.test.framework.spi.container.inmemory.InMemoryTestContainerFactory; 21 | 22 | /** 23 | * A low-level test-container factory. Unlike {@link InMemoryTestContainerFactory}, this factory 24 | * does not override set filters and can thus be used to test resources where custom filters are 25 | * needed. 26 | * 27 | * @author michael.lex 28 | */ 29 | public class FilteringInMemoryTestContainerFactory implements TestContainerFactory { 30 | 31 | @Override 32 | public Class supports() { 33 | return LowLevelAppDescriptor.class; 34 | } 35 | 36 | @Override 37 | public TestContainer create(URI baseUri, AppDescriptor ad) { 38 | if (!(ad instanceof LowLevelAppDescriptor)) 39 | throw new IllegalArgumentException( 40 | "The application descriptor must be an instance of LowLevelAppDescriptor"); 41 | 42 | return new FilteringInMemoryTestContainer(baseUri, (LowLevelAppDescriptor) ad); 43 | } 44 | 45 | private static class FilteringInMemoryTestContainer implements TestContainer { 46 | 47 | private static final Logger LOGGER = Logger.getLogger(FilteringInMemoryTestContainer.class 48 | .getName()); 49 | 50 | final URI baseUri; 51 | 52 | final ResourceConfig resourceConfig; 53 | 54 | final WebApplication webApp; 55 | 56 | /** 57 | * Creates an instance of {@link FilteringInMemoryTestContainer} 58 | * 59 | * @param baseUri 60 | * URI of the application 61 | * @param ad 62 | * instance of {@link LowLevelAppDescriptor} 63 | */ 64 | private FilteringInMemoryTestContainer(URI baseUri, LowLevelAppDescriptor ad) { 65 | this.baseUri = UriBuilder.fromUri(baseUri).build(); 66 | 67 | LOGGER.info("Creating low level InMemory test container configured at the base URI " 68 | + this.baseUri); 69 | 70 | this.resourceConfig = ad.getResourceConfig(); 71 | this.webApp = initiateWebApplication(resourceConfig); 72 | } 73 | 74 | @Override 75 | public Client getClient() { 76 | ClientConfig clientConfig = null; 77 | Set providerSingletons = resourceConfig.getProviderSingletons(); 78 | 79 | if (providerSingletons.size() > 0) { 80 | clientConfig = new DefaultClientConfig(); 81 | for (Object providerSingleton : providerSingletons) { 82 | clientConfig.getSingletons().add(providerSingleton); 83 | } 84 | } 85 | 86 | Client client = (clientConfig == null) ? new Client(new TestResourceClientHandler( 87 | baseUri, webApp)) : new Client(new TestResourceClientHandler(baseUri, webApp), 88 | clientConfig); 89 | 90 | return client; 91 | } 92 | 93 | @Override 94 | public URI getBaseUri() { 95 | return baseUri; 96 | } 97 | 98 | @Override 99 | public void start() { 100 | if (!webApp.isInitiated()) { 101 | LOGGER.info("Starting low level InMemory test container"); 102 | 103 | webApp.initiate(resourceConfig); 104 | } 105 | } 106 | 107 | @Override 108 | public void stop() { 109 | if (webApp.isInitiated()) { 110 | LOGGER.info("Stopping low level InMemory test container"); 111 | 112 | webApp.destroy(); 113 | } 114 | } 115 | 116 | private WebApplication initiateWebApplication(ResourceConfig rc) { 117 | WebApplication webapp = WebApplicationFactory.createWebApplication(); 118 | return webapp; 119 | } 120 | 121 | } 122 | } --------------------------------------------------------------------------------