title: Integration Testing Spring Boot With MockMVC
body: <p>I'm having some trouble testing a Spring Boot application with MockMvc.</p>
  
  <p>I have the following test class:</p>
  
  <pre><code>@RunWith(SpringJUnit4ClassRunner.class)
  @SpringApplicationConfiguration(classes = {SpringConfiguration.class, SecurityConfiguration.class})
  @IntegrationTest({"server.port=8080"})
  @WebAppConfiguration
  public class DemoTest {
  
  @Autowired
  private EmbeddedWebApplicationContext webApplicationContext;
  
  private MockMvc mockMvc;
  
  @Before
  public void setUp() throws Exception {
      mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
  }
  
  @Test
  public void testGetAccountUnauthenticated() throws Exception {
      mockMvc.perform(get("/accounts/1").accept(MediaType.APPLICATION_JSON))
              .andExpect(status().isUnauthorized());
  }
  }
  </code></pre>
  
  <p>This results in a HTTP 200 not a 401. I have component scanning and autoconfiguration enabled and spring security is configured in my SecuityConfiguration class as follows:</p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  @EnableWebMvcSecurity // required for use of @AuthenticationPrincipal in MVC controllers.
  public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  
  @Override
  public void configure(WebSecurity web) {
      web.debug(true);
  }
  
  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
      //set up authentication.
  }
  
  @Override
  protected void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests().anyRequest().authenticated();
     // set up form login
  }
  }
  </code></pre>
  
  <p>If I use a RestTemplate to access <code>http://localhost:8080/accounts/1</code> then I get the expected behaviour (HTTP 401).</p>
  
  <p>I have seen other examples (e.g. <a href="https://stackoverflow.com/questions/23335200/spring-boot-setup-security-for-testing">Spring Boot setup security for testing</a>) that suggest that I autowire the <code>FilterChainProxy</code> and add the filter manually using the <code>WebApplicationContext.addFilters(filterChainProxy)</code> method. However, this actually fails for me (<code>org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.web.FilterChainProxy] found</code>).</p>
  
  <p>I have two questions:</p>
  
  <ol>
  <li>Why does the injected WebApplicationContext not automatically use the SpringSecurity filters? Even if I could get the FilterChainProxy and add it manually, the JavaDoc for EmbeddedWebApplicationContext states </li>
  </ol>
  
  <blockquote>
    <p>any {@link Servlet} or {@link Filter} beans defined in the context will be automatically registered with the embedded Servlet container</p>
  </blockquote>
  
  <p>As a result I wouldn't expect to have to manually add the security filter chain since I (incorrectly?) expect this to "just work" due to the Auto Configuration magic in Spring Boot?</p>
  
  <ol start="2">
  <li>Why is there no FilterChainProxy in the application context? Again, perhaps my expectations of the AutoConfiguration is incorrect - but I thought that this would be configured as part of the context configuration.</li>
  </ol>
  
  <p>Thanks in advance for any advice.</p>
  
  <hr/>
  
  <h3>Edits</h3>
  
  <ul>
  <li><p>The reason a FilterChainProxy doesn't get injected was because I has my configuration set to</p>
  
  <p>public void configure(WebSecurity web) {
      web.debug(true);
  }</p></li>
  </ul>
  
  <p>This actually configures a <code>org.springframework.security.web.debug.DebugFilter</code> instead. The way I have now managed to get the Filter regardless of this debug setting is as follows:</p>
  
  <pre><code>@Resource(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
  private Filter securityFilter;
  </code></pre>
  
  <p>If I add this to the MockMvcBuilder as follows:</p>
  
  <pre><code>MockMvcBuilders.webAppContextSetup(webApplicationContext).addFilters(securityFilter)
  </code></pre>
  
  <p>then it does work as expected.</p>
  
  <p>But, I don't understand why MockMVC would ignore the filters as this seems important for testing a request since anything could happen in a Filter that might impact the outcome of the test. Furthermore, it means that to test properly I'd need to lookup all Filters in the servlet context and establish their priority/url mapping and add them appropriately. This seems error prone and unnecessary.</p>