26

I'm trying to test my login page using mvc-test. I was working pretty good before I added spring security.

My code is:

 mockMvc.perform(
     post("j_spring_security_check")
                    .param(LOGIN_FORM_USERNAME_FIELD, testUsernameValue)
                    .param(LOGIN_FORM_PASSWORD_FIELD, testPasswordValue))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(model().attribute(LOGIN_PAGE_STATUS_VALUE, LOGIN_PAGE_STATUS_FALSE_INDICATOR));

Test class has correct annotations added:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:security-context.xml", "classpath:applicationContext.xml", "classpath:test-contexts/test-context.xml" })

My filter is defined (in web.xml):

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

When I try to add web.xml in @ContextConfiguration it fails, when I remove it I'm getting an Exception:

java.lang.AssertionError: Status expected:<200> but was:<405>

Is there any way to add DelegatingProxyFilter to test context with configuration defined in my security-context.xml to make it works? I tried few tutorials with injecting FilterProxyChain, but it is not working in my case.

Can someone help me with that? Thanks in advance

Shaun the Sheep
  • 22,353
  • 1
  • 72
  • 100
wojtek
  • 493
  • 1
  • 7
  • 12
  • dont think u can test security filters this way, as it is not a full-fledged http server tat is hosted, its rather just a way to resolve rls that spring-mvc-test provides. You might have to just rely on unit tests for the individual pieces in the authentication bit. – redzedi Jan 28 '13 at 17:02

2 Answers2

60

UPDATE: Spring Security 4+ provides out of the box integration with MockMvc. In order to use it ensure you use apply(springSecurity()) as shown below:

import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class MockMvcSecurityTests {

    @Autowired
    private WebApplicationContext context;

    private MockMvc mvc;

    @Before
    public void setup() {
        mvc = MockMvcBuilders
                .webAppContextSetup(context)
                .apply(springSecurity())
                .build();
    }
    ...
}

Original Answer

I'm not sure what you mean by "When I try to add web.xml in @ContextConfiguration it fails", however, you can use Spring Test MVC to validate Spring Security. There is a very good example outlined in the spring-test-mvc project.

The basic outline would look something like this:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:security-context.xml", "classpath:applicationContext.xml", "classpath:test-contexts/test-context.xml" })
public class MyTests {

    @Autowired
    private FilterChainProxy springSecurityFilterChain;

    @Autowired
    private WebApplicationContext wac;

    private MockMvc mockMvc;

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

The idea is that you @Autowire the FilterChainProxy (what the DelegatingProxyFilter delegates to) and instruct MockMvc to use the FilterChainProxy.

NOTE spring-test-mvc is integrated into spring-test-3.2+ and a separate project for Spring 3.1.x, so you can use the example fairly interchangeably (spring-test-mvc does not have support for @WebAppConfiguration and has to use WebContextLoader instead).

Rob Winch
  • 21,440
  • 2
  • 59
  • 76
  • Great gihub link! Thank you! – Tomasz Kalkosiński Jul 16 '13 at 08:56
  • 3
    NB. The spring boot starter POM for spring-security does not include spring-security-test. I had to add it to my main POM to pick up springSecurity() –  Jun 28 '16 at 11:19
  • 1
    Boot uses the spring security bom which includes spring-security-test in 4.1.0+ – Rob Winch Jun 28 '16 at 12:09
  • 1
    @Rob I have spring-boot-starter-security, spring-boot-starter-test and spring-security-test (4.1.0.RELEASE) with Spring Boot 1.3.5. If I remove spring-security-test then it doesn't work for me. –  Jun 28 '16 at 12:42
  • Sorry I misunderstood. Yes you need to include spring-security-test. However, you do not need to provide a version. – Rob Winch Jun 28 '16 at 16:18
2

Add in pom.xml

<repository>
    <id>spring-snaspho</id>
    <url>http://repo.springsource.org/libs-milestone/</url>
</repository>

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <version>4.0.0.M1</version>
</dependency>

and use org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors for authorization request. See the sample usage at https://github.com/rwinch/spring-security-test-blog (https://jira.spring.io/browse/SEC-2592)

Grigory Kislin
  • 16,647
  • 10
  • 125
  • 197