Тестирование Spring Security Controller с использованием Spring Mvc Test

Форма входа в систему jsp и конфигурация Spring Security XML выглядят так:

<spring:url value="/j_spring_security_check" var="login" />
<form action="${login}" method="POST">
<fieldset>
    <legend>Login</legend>
        <input type="text" name="j_username" id="username" placeholder="Usename"/>
        <input type="text" name="j_password" id="password" placeholder="Password"/>
        <input type="submit" value="Login" />
</fieldset>
</form>
...
<security:form-login login-page="/public/authentication/login.htm"
     login-processing-url="/j_spring_security_check"
     default-target-url="/public/index.htm"
     authentication-failure-url="/public/authentication/login.htm?authenticationNok=1"/>

Вот тест для представления формы:

@Test
public void testLoginPostController() throws Exception {
    Account account = new AccountBuilder("test", "test", "[email protected]", Address.FAKE_EMPTY_ADDRESS4TESTS)
            .build();
    this.mockMvc.perform(post("/j_spring_security_check").param("j_username", account.getUsername()).param("j_password", "test"))
            .andDo(print())
            .andExpect(status().isMovedTemporarily())
            .andExpect(view().name("redirect:/public/index.htm"));
}

Но я получаю: java.lang.AssertionError: Status expected:<302> but was:<404>

Когда я открываю страницу входа в браузер, я вижу, что сгенерированная форма:

<form action="/SpringMvcExample/j_spring_security_check" method="POST">

Хорошо, я попытался изменить тест на:

this.mockMvc.perform(post("/SpringMvcExample/j_spring_security_check").param("j_username", account.getUsername()).param("j_password", "test"))

Но получил тот же результат. В то же время, когда я отправляю форму входа в браузер, он перенаправляет меня на страницу public/index.htm, как и ожидалось в тесте.

Что я делаю не так?


person Alexandr    schedule 04.12.2013    source источник


Ответы (2)


ОБНОВЛЕНИЕ: в Spring Security 4 добавлена ​​официальная ссылка Тестовая поддержка. Существует раздел, описывающий тестирование с MockMvc в деталях.

Похоже, вы не добавили Spring Security Filter в свой MockMvc. Например:

public class MyTests {

    @Autowired
    private FilterChainProxy springSecurityFilterChain;

    @Autowired
    private WebApplicationContext wac;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webApplicationContextSetup(this.wac)
            .addFilters(this.springSecurityFilterChain).build();
    }

    @Test
    public void testLoginPostController() throws Exception {
        Account account = new AccountBuilder("test", "test", "[email protected]", Address.FAKE_EMPTY_ADDRESS4TESTS)
                .build();
        this.mockMvc.perform(post("/j_spring_security_check").param("j_username", account.getUsername()).param("j_password", "test"))
                .andDo(print())
                .andExpect(status().isMovedTemporarily())
                .andExpect(view().name("redirect:/public/index.htm"));
    }

}

Причина, по которой это происходит, заключается в том, что прямо сейчас MockMvc знает только о вашей конфигурации Spring MVC и не знает ни о каком фильтре (то есть о FilterChainProxy). Поскольку проверка имени пользователя и пароля (т. е. обработка /j_spring_security_check) происходит в FilterChainProxy перед его отправкой в ​​Spring MVC, и вы не включили его, вы получаете 404.

person Rob Winch    schedule 05.12.2013

/j_spring_security_check — это специальный адрес, обрабатываемый Spring Security (возможно, через его фильтр, но я этого не проверял). Это не обработчик запросов, зарегистрированный в Spring MVC, поэтому вы не можете использовать MockMVC для его тестирования.

Вам нужно будет запустить реальный контейнер приложения и использовать что-то HttpClient или Selenium.

person billc.cn    schedule 04.12.2013