Mocking SecurityContext in Jersey Tests

Share on:

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.

comments powered by Disqus