Mocking SecurityContext in Jersey Tests
Jersey can be used to write integration tests for REST APIs. In this tutorial, you'll learn how to mock a SecurityContext in your tests.
Join the DZone community and get the full member experience.
Join For FreeJersey has a great possibility to write integration tests for REST APIs, written with Jersey. Just extend the class JerseyTest and go for it.
I ran into 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:
@Path("hello/world")
public class MyJerseyResource {
@GET
public Response helloWorld(@Context final SecurityContext context) {
String name = context.getUserPrincipal().getName();
return Response.ok("Hello " + name, MediaType.TEXT_PLAIN).build();
}
}
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
final SecurityContext securityContextMock = mock(SecurityContext.class);
when(securityContextMock.getUserPrincipal()).thenReturn(new Principal() {
@Override
public String getName() {
return "Alice";
}
});
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:
@Override
public Application configure() {
final SecurityContext securityContextMock = mock(SecurityContext.class);
when(securityContextMock.getUserPrincipal()).thenReturn(new Principal() {
@Override
public String getName() {
return "Alice";
}
});
ResourceConfig config = new ResourceConfig();
config.register(new ContainerRequestFilter() {
@Override
public void filter(final ContainerRequestContext containerRequestContext) throws IOException {
containerRequestContext.setSecurityContext(securityContextMock);
}
});
return config;
}
Then, the whole test for my resource looks like the following one:
public class MyJerseyResourceTest extends JerseyTest {
@Test
public void helloWorld() throws Exception {
Response response = target("hello/world").request().get();
assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_OK);
assertThat(response.getEntity()), isEqualTo("Hello Alice");
}
@Override
public Application configure() {
final SecurityContext securityContextMock = mock(SecurityContext.class);
when(securityContextMock.getUserPrincipal()).thenReturn(new Principal() {
@Override
public String getName() {
return "Alice";
}
});
ResourceConfig config = new ResourceConfig();
config.register(new ContainerRequestFilter() {
@Override
public void filter(final ContainerRequestContext containerRequestContext) throws IOException {
containerRequestContext.setSecurityContext(securityContextMock);
}
});
return config;
}
Do you have a smarter solution for this problem? Let me know it and write a comment below.
Published at DZone with permission of Sandra Parsick, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments