2012-12-03 2 views
15

통합 테스트를 실행하려면 3.1 버전의 새로운 spring-test을 사용하고 있습니다. 그것은 잘 작동하지만 세션을 작동시킬 수는 없습니다. 내 코드 :Spring mvc 3.1 세션 지원이 포함 된 통합 테스트

@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()); 
    } 
} 

요청할 때마다 내 세션이 비어 있습니다. 이유를 모르겠습니다.

편집 : 마지막 어설 션이 실패했습니다 : andExpect(status().isOk());. 그것은 200 대신에 403을 반환합니다.

+0

어설 션 중 실패한 것은 무엇입니까? –

+0

마지막 하나 :'andExpect (status(). isOk());'내가 설정해야하는 변수에 대한 세션을 확인했기 때문에 세션이 비어있어 금지 된 상태로 되돌아갑니다. – islon

+0

참고 [봄 3.2 새로운 mvc 테스트로 사용자 로그인하는 법] (http://stackoverflow.com/questions/14308341/how-to-login-a-user-with-spring-3-2-new-mvc 테스트). – Arjan

답변

9

저는 다소 로터리 방식으로 이것을했습니다 - 작동합니다.

을 :

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 그냥 세션을 개최, 내 사용자 정의 클래스입니다 : 내가 한 일은 봄 - 보안 세션에 채워 관련 보안 속성으로 세션을 생성하고 해당 세션이 방법을 잡을 수 있도록했다

private static final class SessionHolder{ 
    private SessionWrapper session; 


    public SessionWrapper getSession() { 
     return session; 
    } 

    public void setSession(SessionWrapper session) { 
     this.session = session; 
    } 
} 

및 SessionWrapper 세션 방법이 필요해서, MockHttpSession MockHttpSession에서 연장 다른 클래스 :이 s의

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); 
    } 

} 

이제 sessionHolder에서 세션을 가져와 예를 들어 후속 메소드를 실행할 수 있습니다. 내 경우 :

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

감사합니다. 작동합니다! – islon

21

업데이트] 답변 :

:

그것은 "sessionAttrs는"빌더에 추가 된 새로운 방법을 보인다

Map<String, Object> sessionAttrs = new HashMap<>(); 
sessionAttrs.put("sessionAttrName", "sessionAttrValue"); 

mockMvc.perform(MockMvcRequestBuilders.get("/uri").sessionAttrs(sessionAttrs)) 
     .andDo(print()) 
     .andExpect(MockMvcResultMatchers.status().isOk()); 

OLD 답변을 (mvc controller test with session attribute 참조) 여기에 지원하는 클래스를 사용하지 않고 동일한 결과를 얻을 수있는 간단한 솔루션입니다, 이것은 내 코드의 스 니펫입니다. (이 메소드가 B iju Kunjummen이 대답했다) :


     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")); 
 
+1

이것은 확실히 받아 들여진 대답 일 것입니다! 현재 받아 들여지는 대답은 이것을 달성하기위한 매우 더러운 해킹입니다. –

+0

정말 좋은 솔루션입니다. http://stackoverflow.com/a/26341909/2674303 – gstackoverflow

+0

이 솔루션을 구현하는 데 문제가 있습니다. 다음 예외를 얻는 중'NestedServletException : 요청 처리가 실패했습니다. 상자의 예외는 java.lang.ArrayIndexOutOfBoundsException : -1'입니다. 어떤 생각이 그것을 일으킬 수 있습니까? – JackB

관련 문제