Spring mvc 3.1 integration tests with session support

I use the new spring-test in version 3.1 to run integration tests. It works very well, but I can't get the session to work. My code is:

@RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration("src/main/webapp") @ContextConfiguration({"classpath:applicationContext-dataSource.xml", "classpath:applicationContext.xml", "classpath:applicationContext-security-roles.xml", "classpath:applicationContext-security-web.xml", "classpath:applicationContext-web.xml"}) public class SpringTestBase { @Autowired private WebApplicationContext wac; @Autowired private FilterChainProxy springSecurityFilterChain; @Autowired private SessionFactory sessionFactory; protected MockMvc mock; protected MockHttpSession mockSession; @Before public void setUp() throws Exception { initDataSources("dataSource.properties"); mock = MockMvcBuilders.webAppContextSetup(wac).addFilters(springSecurityFilterChain).build(); mockSession = new MockHttpSession(wac.getServletContext(), UUID.randomUUID().toString()); } @Test public void testLogin() throws Exception { // this controller sets a variable in the session mock.perform(get("/") .session(mockSession)) .andExpect(model().attributeExists("csrf")); // I set another variable here just to be sure mockSession.setAttribute(CSRFHandlerInterceptor.CSRF, csrf); // this call returns 403 instead of 200 because the session is empty... mock.perform(post("/setup/language") .session(mockSession) .param(CSRFHandlerInterceptor.CSRF, csrf) .param("language", "de")) .andExpect(status().isOk()); } } 

My session is empty in every request, I don’t know why.

EDIT: The last statement fails: andExpect(status().isOk()); . It returns 403 instead of 200.

+15
java spring spring-mvc testing
Dec 03 '12 at 16:01
source share
2 answers

I did this in a somewhat workaround - it works. What I did was let Spring-Security create a session with the appropriate security attributes populated in the session, and then grab that session as follows:

  this.mockMvc.perform(post("/j_spring_security_check") .param("j_username", "fred") .param("j_password", "fredspassword")) .andExpect(status().isMovedTemporarily()) .andDo(new ResultHandler() { @Override public void handle(MvcResult result) throws Exception { sessionHolder.setSession(new SessionWrapper(result.getRequest().getSession())); } }); 

SessionHolder is my custom class, just to host a session:

 private static final class SessionHolder{ private SessionWrapper session; public SessionWrapper getSession() { return session; } public void setSession(SessionWrapper session) { this.session = session; } } 

and SessionWrapper is another class that extends from MockHttpSession, just because the session method requires MockHttpSession:

 private static class SessionWrapper extends MockHttpSession{ private final HttpSession httpSession; public SessionWrapper(HttpSession httpSession){ this.httpSession = httpSession; } @Override public Object getAttribute(String name) { return this.httpSession.getAttribute(name); } } 

With this set, now you can simply take a session from sessionHolder and execute the following methods, for example. in my case:

 mockMvc.perform(get("/membersjson/1").contentType(MediaType.APPLICATION_JSON).session(sessionHolder.getSession())) .andExpect(status().isOk()) .andExpect(content().string(containsString("OneUpdated"))); 
+9
Dec 03
source share

UPDATED RESPONSE:

It seems the new method "sessionAttrs" has been added to the constructor (see mvc controller test with session attribute )

 Map<String, Object> sessionAttrs = new HashMap<>(); sessionAttrs.put("sessionAttrName", "sessionAttrValue"); mockMvc.perform(MockMvcRequestBuilders.get("/uri").sessionAttrs(sessionAttrs)) .andDo(print()) .andExpect(MockMvcResultMatchers.status().isOk()); 

OLD RESPONSE:

here is a simpler solution to achieve the same result without using helper classes, this is a piece of code (I don’t know if these methods were already available when Biju Kunjummen answered):

 HttpSession session = mockMvc.perform(post("/login-process").param("j_username", "user1").param("j_password", "user1")) .andExpect(status().is(HttpStatus.FOUND.value())) .andExpect(redirectedUrl("/")) .andReturn() .getRequest() .getSession(); Assert.assertNotNull(session); mockMvc.perform(get("/").session((MockHttpSession)session).locale(Locale.ENGLISH)) .andDo(print()) .andExpect(status().isOk()) .andExpect(view().name("logged_in"));
HttpSession session = mockMvc.perform(post("/login-process").param("j_username", "user1").param("j_password", "user1")) .andExpect(status().is(HttpStatus.FOUND.value())) .andExpect(redirectedUrl("/")) .andReturn() .getRequest() .getSession(); Assert.assertNotNull(session); mockMvc.perform(get("/").session((MockHttpSession)session).locale(Locale.ENGLISH)) .andDo(print()) .andExpect(status().isOk()) .andExpect(view().name("logged_in")); 
+21
Aug 12 '13 at 15:18
source share



All Articles