diff --git a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/MockMvcAutoConfiguration.java b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/MockMvcAutoConfiguration.java index 24cc252b6a..401096a8f4 100644 --- a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/MockMvcAutoConfiguration.java +++ b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/MockMvcAutoConfiguration.java @@ -22,34 +22,41 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration; +import org.springframework.boot.autoconfigure.web.WebMvcProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.test.web.servlet.DispatcherServletCustomizer; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvcBuilder; import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; /** * Auto-configuration for {@link MockMvc}. * * @author Phillip Webb * @author Andy Wilkinson + * @author Stephane Nicoll * @see AutoConfigureWebMvc * @since 1.4.0 */ @Configuration @ConditionalOnWebApplication @AutoConfigureAfter(WebMvcAutoConfiguration.class) -@EnableConfigurationProperties +@EnableConfigurationProperties(WebMvcProperties.class) public class MockMvcAutoConfiguration { private final WebApplicationContext context; + private final WebMvcProperties webMvcProperties; - MockMvcAutoConfiguration(WebApplicationContext context) { + MockMvcAutoConfiguration(WebApplicationContext context, + WebMvcProperties webMvcProperties) { this.context = context; + this.webMvcProperties = webMvcProperties; } @Bean @@ -57,6 +64,8 @@ public class MockMvcAutoConfiguration { public DefaultMockMvcBuilder mockMvcBuilder( List customizers) { DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(this.context); + builder.addDispatcherServletCustomizer( + new MockMvcDispatcherServletCustomizer(this.webMvcProperties)); for (MockMvcBuilderCustomizer customizer : customizers) { customizer.customize(builder); } @@ -75,4 +84,25 @@ public class MockMvcAutoConfiguration { return builder.build(); } + private static class MockMvcDispatcherServletCustomizer + implements DispatcherServletCustomizer { + + private final WebMvcProperties webMvcProperties; + + MockMvcDispatcherServletCustomizer(WebMvcProperties webMvcProperties) { + this.webMvcProperties = webMvcProperties; + } + + @Override + public void customize(DispatcherServlet dispatcherServlet) { + dispatcherServlet.setDispatchOptionsRequest( + this.webMvcProperties.isDispatchOptionsRequest()); + dispatcherServlet.setDispatchTraceRequest( + this.webMvcProperties.isDispatchTraceRequest()); + dispatcherServlet.setThrowExceptionIfNoHandlerFound( + this.webMvcProperties.isThrowExceptionIfNoHandlerFound()); + } + + } + } diff --git a/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/servlet/ExampleControllerAdvice.java b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/servlet/ExampleControllerAdvice.java index 47e33229e8..34433465ee 100644 --- a/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/servlet/ExampleControllerAdvice.java +++ b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/servlet/ExampleControllerAdvice.java @@ -16,14 +16,18 @@ package org.springframework.boot.test.autoconfigure.web.servlet; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.servlet.NoHandlerFoundException; /** * Example {@link ControllerAdvice} used with {@link WebMvcTest} tests. * * @author Phillip Webb + * @author Stephane Nicoll */ @ControllerAdvice public class ExampleControllerAdvice { @@ -33,4 +37,11 @@ public class ExampleControllerAdvice { return ResponseEntity.ok("recovered"); } + @ExceptionHandler(NoHandlerFoundException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ResponseEntity noHandlerFoundHandler(NoHandlerFoundException exception) { + return ResponseEntity.badRequest() + .body("Invalid request: " + exception.getRequestURL()); + } + } diff --git a/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/servlet/WebMvcTestCustomDispatcherServletIntegrationTests.java b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/servlet/WebMvcTestCustomDispatcherServletIntegrationTests.java new file mode 100644 index 0000000000..a4a407626a --- /dev/null +++ b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/servlet/WebMvcTestCustomDispatcherServletIntegrationTests.java @@ -0,0 +1,53 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.web.servlet; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.web.servlet.DispatcherServlet; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * Tests for Test {@link DispatcherServlet} customizations. + * + * @author Stephane Nicoll + */ +@RunWith(SpringRunner.class) +@WebMvcTest(secure = false) +@TestPropertySource(properties = { "spring.mvc.throw-exception-if-no-handler-found=true", + "spring.mvc.static-path-pattern=/static/**" }) +public class WebMvcTestCustomDispatcherServletIntegrationTests { + + @Autowired + private MockMvc mvc; + + @Test + public void dispatcherServletIsCustomized() throws Exception { + this.mvc.perform(get("/does-not-exist")) + .andExpect(status().isBadRequest()) + .andExpect(content().string("Invalid request: /does-not-exist")); + } + +}