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:
@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 on Java Code Geeks with permission by Sandra Parsick, partner at our JCG program. See the original article here: Mocking SecurityContext in Jersey Tests Opinions expressed by Java Code Geeks contributors are their own. |
A good article that could be a little bitter with the appropriate Maven/Gradle dependencies and imports for the Java classes involved.