Mocking SecurityContext in Jersey Tests
Jersey has a great possibility to write integration test for REST-APIs, written with Jersey. Just extend the class JerseyTest
and go for it. I ran in an issue, where I had to mock a SecurityContext
, so that the SecurityContext
includes a special UserPrincipal
. The challenge is that Jersey wraps the SecurityContext
in an own class SecurityContextInjectee
in tests. So I have to add my SecurityContext
Mock to this Jersey's wrapper class. Let me demonstrate it in an example. Let say I have the following Jersey Resource:
1import javax.ws.rs.*;
2import javax.ws.rs.core.*;
3
4@Path("hello/world")
5public class MyJerseyResource {
6
7 @GET
8 public Response helloWorld(@Context final SecurityContext context) {
9 String name = context.getUserPrincipal().getName();
10 return Response.ok("Hello " + name, MediaType.TEXT_PLAIN).build();
11 }
12}
In my test, I have to mock the SecurityContext
, so that a predefined user principal can be used during the tests. I use Mockito as mocking framework. My mock looks like the following one
1import java.security.Principal;
2import javax.ws.rs.core.SecurityContext;
3
4import static org.mockito.Mockito.mock;
5import static org.mockito.Mockito.when;
6
7final SecurityContext securityContextMock = mock(SecurityContext.class);
8when(securityContextMock.getUserPrincipal()).thenReturn(new Principal() {
9 @Override
10 public String getName() {
11 return "Alice";
12 }
13});
For adding this mocked SecurityContext
to the wrapper class SecurityContextInjectee
, I have to configure a ResourceConfig
with a modified ContainerRequestContext
in my Jersey Test. The mocked SecurityContext
can be set in this modified ContainerRequestContext
and then it will be used in the wrapper class:
1import java.security.Principal;
2
3import javax.ws.rs.container.ContainerRequestContext;
4import javax.ws.rs.container.ContainerRequestFilter;
5import javax.ws.rs.core.SecurityContext;
6
7import org.glassfish.jersey.server.ResourceConfig;
8import static org.mockito.Mockito.mock;
9import static org.mockito.Mockito.when;
10
11@Override
12public Application configure() {
13 final SecurityContext securityContextMock = mock(SecurityContext.class);
14 when(securityContextMock.getUserPrincipal()).thenReturn(new Principal() {
15 @Override
16 public String getName() {
17 return "Alice";
18 }
19 });
20
21 ResourceConfig config = new ResourceConfig();
22 config.register(new ContainerRequestFilter(){
23 @Override
24 public void filter(final ContainerRequestContext containerRequestContext) throws IOException {
25 containerRequestContext.setSecurityContext(securityContextMock);
26 }
27 });
28 return config;
29}
Then, the whole test for my resource looks like the following one:
1import java.security.Principal;
2
3import javax.ws.rs.container.ContainerRequestContext;
4import javax.ws.rs.container.ContainerRequestFilter;
5import javax.ws.rs.core.Application;
6import javax.ws.rs.core.Response;
7import javax.ws.rs.core.SecurityContext;
8
9import org.apache.commons.httpclient.HttpStatus;
10import org.glassfish.jersey.server.ResourceConfig;
11import org.glassfish.jersey.test.JerseyTest;
12import org.junit.Test;
13import static org.assertj.core.api.Assertions.assertThat;
14import static org.mockito.Mockito.mock;
15import static org.mockito.Mockito.when;
16
17public class MyJerseyResourceTest extends JerseyTest {
18
19 @Test
20 public void helloWorld() throws Exception {
21 Response response = target("hello/world").request().get();
22
23 assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_OK);
24 assertThat(response.getEntity()).isEqualTo("Hello Alice");
25 }
26
27 @Override
28 public Application configure() {
29 final SecurityContext securityContextMock = mock(SecurityContext.class);
30 when(securityContextMock.getUserPrincipal()).thenReturn(new Principal() {
31 @Override
32 public String getName() {
33 return "Alice";
34 }
35 });
36
37 ResourceConfig config = new ResourceConfig();
38 config.register(new ContainerRequestFilter() {
39 @Override
40 public void filter(final ContainerRequestContext containerRequestContext) throws IOException {
41 containerRequestContext.setSecurityContext(securityContextMock);
42 }
43 });
44 return config;
45 }
46}
Do you have a smarter solution for this problem? Let me know it and write a comment below.