Reputation: 12741
I'm setting up unit tests for my Spring MVC Controllers and I am attempting to leverage the Spring MVC test framework. For each endpoint in my controller, I want to ensure that only users with designated authorities have access. My problem is that I use a custom User implementation and get class cast exceptions when using the mockMvc tooling around this.
For each request, I expect it to look something like this:
mockMvc.perform(MockMvcRequestBuilders.get(path).with(user("user").authorities(authorities)))
.andExpect(status().isOk())
.andExpect(authenticated().withUsername("user"));
I would like to somehow tweak the above statement to specify my custom user principal. See Spring's user method below. My first thought was I would override the class UserRequestPostProcessor
and tweak it so that it's using my custom user type instead of the standard Spring Security user, but this class is declared as final and cannot be subclassed. Is there any support for overriding the default behavior and using a custom user type??
public static UserRequestPostProcessor user(String username) {
return new UserRequestPostProcessor(username);
}
From what I have seen, I am a candidate for annotating my tests with @WithSecurityContext so that I can set my custom user principal in the Authentication. My concern here is that I would be limited to testing one user for each method and this doesn't scale for what I am trying to do.
How can I test requests made by multiple custom users?
Upvotes: 4
Views: 4823
Reputation: 12741
I learned of two ways to do this:
I could create a class that implements UserDetails and extends my custom user principal class. I could then pass this as a parameter to the user method.
I can scratch the user method altogether, and pass in my Authentication already set with my custom user principal.
I went with the latter.
protected void performTest(HttpMethod method, String path, Object[] pathVariables, UserRoleEnum role,
boolean expectAllowed) throws Exception {
mockMvc.perform(buildRequest(method, path, pathVariables).with(authentication(createAuthentication(role))))
.andExpect(expectAllowed ? status().isNotFound() : status().isForbidden())
.andExpect(authenticated().withUsername("user"));
}
note - the buildRequest
and createAuthentication
methods are helper methods that I created, whereas all the other methods are provided by Spring. The helper methods return MockHttpServletRequestBuilder
and Authentication
respectively.
Upvotes: 2