Spring 3 MVC Controller integration test - inject

2019-04-09 07:09发布

问题:

As part of Spring 3 MVC it is possible to inject the currently logged in user (Principle) object into a controller method.

E.g.

@Controller
public class MyController {

    @RequestMapping(value="/update", method = RequestMethod.POST)
    public String update(ModelMap model, Principal principal) {

       String name = principal.getName();
       ... the rest here
    }
}

This is documented as part of the Spring 3 documentation here: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping-arguments.

This works in the production code. However I don't know how to test this. When I create an integration test (having set up spring security context as well) and call the controller handle method then the Principal is always null!

public class FareTypeControllerIntegrationTest extends SpringTestBase {

@Autowired
private MyController controller;

@Autowired
private AnnotationMethodHandlerAdapter handlerAdapter;

private final MockHttpServletRequest request = new MockHttpServletRequest();
private final MockHttpServletResponse response = new MockHttpServletResponse();

@Test
public void testUpdate() throws Exception {
    request.setRequestURI("/update");
    request.setMethod(HttpMethod.POST.name());
    ... setup rest of request

    ModelAndView mav = handlerAdapter.handle(request, response, controller);

    .. rest of assertions

}

The tests are running correctly and everything except the Principal is null.

Any ideas?

TIA

Ayub

回答1:

After a quick look into Spring sources this should work:

request.setUserPrincipal(somePrincipal);


回答2:

I've tried to do this some time ago, here is the method i used to set up authentication.

protected void setSecurityContext(String login){
            userDetailsTest = userManager.loadUserByUsername(login);
            TestingAuthenticationToken testingAuthenticationToken = new TestingAuthenticationToken(userDetailsTest, userDetailsTest.getAuthorities());
            SecurityContext securityContext = new SecurityContextImpl();
            securityContext.setAuthentication((Authentication) testingAuthenticationToken);
            SecurityContextHolder.setContext(securityContext);
         } 

Then i just call it in the @Before method of the test. Hope it helps.



回答3:

I do something like this in my tests prior to calling code using Spring Security (such as the Principal parameter resolver you are testing):

SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("wiseau", "Love is blind"));