Reputation: 15254
I have spring-security-oauth2 application which is a ResourceServer. We have a custom PrincipalExtractor
class that builds the custom Principal object. This custom Principal object do not extend Principal
or UserDetails
class CustomUser{
//some custom fields
}
class CustomPrincipalExtractor implements PrincipalExtractor{
@Override
public CustomUser extractPrincipal(Map<String, Object> map){
return new CustomUser(map);
}
}
class SomeController{
@GetMapping
public ResponseEntity(@AuthenticationPrincipal CustomUser user){
//able to get user object
}
}
The above code works fine. Now I want to test the controller, but not able to pass CustomUser instance.
@SpringBootTest
@AutoConfigureMockMvc
public class SomeControllerTest{
@Autowired
private MockMvc mockMvc;
@Test
public void test(){
mockMvc.perform(get(...).principal(CANNOT pass CustomUser as it does not implement Principal))
}
}
I looked at some other solutions which asks to have custom HandlerMethodArgumentResolver
but not sure how configure autoconfigured MockMvc
Upvotes: 5
Views: 6156
Reputation: 15254
I had to implement some workaround to get this work.
Created a mock Filter that sets the Authentication object in SecurityContext. Following is the code
public class MockSpringSecurityFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
SecurityContextHolder.getContext()
.setAuthentication((Authentication) ((HttpServletRequest) req).getUserPrincipal());
chain.doFilter(req, res);
}
@Override
public void destroy() {
SecurityContextHolder.clearContext();
}
}
Within the test
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(context)
.apply(springSecurity(new MockSpringSecurityFilter()))
.build();
}
@Test
public void test(){
mockMvc.perform(get(...)
.principal(new UsernamePasswordAuthenticationToken(new CustomUser(), null))...
}
Upvotes: 3