Spring mvc 3.1 интеграционные тесты с поддержкой сеанса - программирование
Подтвердить что ты не робот

Spring mvc 3.1 интеграционные тесты с поддержкой сеанса

Я использую новый spring -test в версии 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());. Он возвращает 403 вместо 200.

4b9b3361

Ответ 1

Я сделал это несколько обходным путем - работает. То, что я сделал, это позволить 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")));

Ответ 2

ОБНОВЛЕННЫЙ ОТВЕТ:

Кажется, новый метод "sessionAttrs" был добавлен в конструктор (см. тест контроллера mvc с атрибутом сеанса)

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

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

СТАРЫЙ ОТВЕТ:

вот более простое решение для достижения того же результата без использования вспомогательных классов, это фрагмент кода (я не знаю, были ли эти методы уже доступны, когда ответил Биджу Кунджуммен):


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