2012-12-03 13 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()); 
    } 
} 

私のセッションはすべての要求で空ですが、なぜわかりません。

EDIT:最後のアサートは失敗しています: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

UPDATED ANSWER:

それは "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 ANSWERを(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

関連する問題