Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing Spring Security Controller Using Spring Mvc Test

Login jsp form and spring security xml configuration look like:

<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"/>

Here is the test for form sumbission:

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

But I'm getting: java.lang.AssertionError: Status expected:<302> but was:<404>

When I open login page in browser I see that the generated form is:

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

Ok, I tried to change test to:

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

But got the same result. At the same time, when I submit the login form in the browser, it redirects me to the public/index.htm page, as exptect in test.

What am I doing wrong?

like image 933
Alexandr Avatar asked Mar 22 '23 10:03

Alexandr


1 Answers

UPDATE: Spring Security 4 has added official Test Support. There is a section that describes testing with MockMvc in detail.

It sounds as though you have not added the Spring Security Filter to your MockMvc. For example:

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

}

The reason this is happening is because right now the MockMvc is only aware of your Spring MVC configuration and is not aware of any Filter (i.e. the FilterChainProxy). Since validation of the username and password (i.e. processing of /j_spring_security_check) occurs within FilterChainProxy before it is sent to Spring MVC and you have not included it you are getting a 404.

like image 185
Rob Winch Avatar answered Apr 02 '23 19:04

Rob Winch