18

3.1 バージョンの新しいspring-testを使用して統合テストを実行しています。それは本当にうまく機能しますが、セッションを機能させることができません。私のコード:

@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 を返します。

4

2 に答える 2

9

私はこれをやや回りくどい方法で行いましたが、うまくいきます。私がしたことは、Spring-Security が関連するセキュリティ属性をセッションに入力してセッションを作成し、そのセッションを次のように取得することでした。

    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 を必要とするためです。

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")));
于 2012-12-03T22:29:07.903 に答える