diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/HttpHandlerAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/HttpHandlerAutoConfigurationTests.java index 9694f47994..8d59b4c0ba 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/HttpHandlerAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/HttpHandlerAutoConfigurationTests.java @@ -16,12 +16,9 @@ package org.springframework.boot.autoconfigure.web.reactive; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.boot.web.reactive.context.GenericReactiveWebApplicationContext; +import org.springframework.boot.test.context.ContextLoader; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.server.reactive.HttpHandler; @@ -37,36 +34,27 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Brian Clozel * @author Stephane Nicoll + * @author Andy Wilkinson */ public class HttpHandlerAutoConfigurationTests { - @Rule - public ExpectedException thrown = ExpectedException.none(); - - private GenericReactiveWebApplicationContext context; + private final ContextLoader contextLoader = new ContextLoader().webReactive() + .autoConfig(HttpHandlerAutoConfiguration.class); @Test public void shouldNotProcessIfExistingHttpHandler() { - load(CustomHttpHandler.class); - assertThat(this.context.getBeansOfType(HttpHandler.class)).hasSize(1); - assertThat(this.context.getBean(HttpHandler.class)) - .isSameAs(this.context.getBean("customHttpHandler")); + this.contextLoader.config(CustomHttpHandler.class).load(context -> { + assertThat(context.getBeansOfType(HttpHandler.class)).hasSize(1); + assertThat(context.getBean(HttpHandler.class)) + .isSameAs(context.getBean("customHttpHandler")); + }); } @Test public void shouldConfigureHttpHandlerAnnotation() { - load(WebFluxAutoConfiguration.class); - assertThat(this.context.getBeansOfType(HttpHandler.class).size()).isEqualTo(1); - } - - private void load(Class config, String... environment) { - this.context = new GenericReactiveWebApplicationContext(); - TestPropertyValues.of(environment).applyTo(this.context); - if (this.context != null) { - this.context.register(config); - } - this.context.register(HttpHandlerAutoConfiguration.class); - this.context.refresh(); + this.contextLoader.autoConfig(WebFluxAutoConfiguration.class).load(context -> { + assertThat(context.getBeansOfType(HttpHandler.class).size()).isEqualTo(1); + }); } @Configuration diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java index 8cc47b1e76..83d6c320a0 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java @@ -16,28 +16,20 @@ package org.springframework.boot.autoconfigure.web.servlet; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.function.Consumer; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.validation.ValidatorFactory; -import org.assertj.core.api.Condition; import org.joda.time.DateTime; -import org.junit.After; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.springframework.beans.DirectFieldAccessor; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.http.HttpMessageConverters; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; @@ -45,11 +37,11 @@ import org.springframework.boot.autoconfigure.validation.ValidationAutoConfigura import org.springframework.boot.autoconfigure.validation.ValidatorAdapter; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.WelcomePageHandlerMapping; -import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.boot.test.context.ContextLoader; import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor; -import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.boot.web.servlet.filter.OrderedHttpPutFormContentFilter; import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -64,13 +56,12 @@ import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.util.ObjectUtils; -import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import org.springframework.validation.Validator; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.web.accept.ContentNegotiationManager; import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; +import org.springframework.web.context.WebApplicationContext; import org.springframework.web.filter.HttpPutFormContentFilter; import org.springframework.web.servlet.HandlerAdapter; import org.springframework.web.servlet.HandlerExceptionResolver; @@ -80,11 +71,11 @@ import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver; import org.springframework.web.servlet.handler.HandlerExceptionResolverComposite; import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver; import org.springframework.web.servlet.i18n.FixedLocaleResolver; -import org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import org.springframework.web.servlet.resource.AppCacheManifestTransformer; @@ -99,6 +90,7 @@ import org.springframework.web.servlet.resource.ResourceHttpRequestHandler; import org.springframework.web.servlet.resource.ResourceResolver; import org.springframework.web.servlet.resource.ResourceTransformer; import org.springframework.web.servlet.resource.VersionResourceResolver; +import org.springframework.web.servlet.resource.VersionStrategy; import org.springframework.web.servlet.view.AbstractView; import org.springframework.web.servlet.view.ContentNegotiatingViewResolver; @@ -122,134 +114,159 @@ public class WebMvcAutoConfigurationTests { private static final MockServletWebServerFactory webServerFactory = new MockServletWebServerFactory(); - @Rule - public ExpectedException thrown = ExpectedException.none(); + private final ContextLoader contextLoader = new ContextLoader() + .autoConfig(WebMvcAutoConfiguration.class, + HttpMessageConvertersAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class) + .config(Config.class).webServlet(); - private AnnotationConfigServletWebServerApplicationContext context; - - @After - public void close() { - if (this.context != null) { - this.context.close(); - } + @Test + public void handlerAdaptersCreated() { + this.contextLoader.load(context -> { + assertThat(context.getBeanNamesForType(HandlerAdapter.class).length) + .isEqualTo(3); + assertThat(context.getBean(RequestMappingHandlerAdapter.class) + .getMessageConverters()).isNotEmpty().isEqualTo( + context.getBean(HttpMessageConverters.class).getConverters()); + }); } @Test - public void handlerAdaptersCreated() throws Exception { - load(); - assertThat(this.context.getBeanNamesForType(HandlerAdapter.class).length) - .isEqualTo(3); - assertThat(this.context.getBean(RequestMappingHandlerAdapter.class) - .getMessageConverters()).isNotEmpty() - .isEqualTo(this.context.getBean(HttpMessageConverters.class) - .getConverters()); + public void handlerMappingsCreated() { + this.contextLoader.load(context -> { + assertThat(context.getBeanNamesForType(HandlerMapping.class).length) + .isEqualTo(7); + }); } @Test - public void handlerMappingsCreated() throws Exception { - load(); - assertThat(this.context.getBeanNamesForType(HandlerMapping.class).length) - .isEqualTo(7); + public void resourceHandlerMapping() { + this.contextLoader.load(context -> { + Map> mappingLocations = getResourceMappingLocations( + context); + assertThat(mappingLocations.get("/**")).hasSize(5); + assertThat(mappingLocations.get("/webjars/**")).hasSize(1); + assertThat(mappingLocations.get("/webjars/**").get(0)) + .isEqualTo(new ClassPathResource("/META-INF/resources/webjars/")); + assertThat(getResourceResolvers(context, "/webjars/**")).hasSize(1); + assertThat(getResourceTransformers(context, "/webjars/**")).hasSize(0); + assertThat(getResourceResolvers(context, "/**")).hasSize(1); + assertThat(getResourceTransformers(context, "/**")).hasSize(0); + }); } @Test - public void resourceHandlerMapping() throws Exception { - load(); - Map> mappingLocations = getResourceMappingLocations(); - assertThat(mappingLocations.get("/**")).hasSize(5); - assertThat(mappingLocations.get("/webjars/**")).hasSize(1); - assertThat(mappingLocations.get("/webjars/**").get(0)) - .isEqualTo(new ClassPathResource("/META-INF/resources/webjars/")); - assertThat(getResourceResolvers("/webjars/**")).hasSize(1); - assertThat(getResourceTransformers("/webjars/**")).hasSize(0); - assertThat(getResourceResolvers("/**")).hasSize(1); - assertThat(getResourceTransformers("/**")).hasSize(0); - } - - @Test - public void customResourceHandlerMapping() throws Exception { - load("spring.mvc.static-path-pattern:/static/**"); - Map> mappingLocations = getResourceMappingLocations(); - assertThat(mappingLocations.get("/static/**")).hasSize(5); - assertThat(getResourceResolvers("/static/**")).hasSize(1); + public void customResourceHandlerMapping() { + this.contextLoader.env("spring.mvc.static-path-pattern:/static/**") + .load(context -> { + Map> mappingLocations = getResourceMappingLocations( + context); + assertThat(mappingLocations.get("/static/**")).hasSize(5); + assertThat(getResourceResolvers(context, "/static/**")).hasSize(1); + }); } @Test public void resourceHandlerMappingOverrideWebjars() throws Exception { - load(WebJars.class); - Map> mappingLocations = getResourceMappingLocations(); - assertThat(mappingLocations.get("/webjars/**")).hasSize(1); - assertThat(mappingLocations.get("/webjars/**").get(0)) - .isEqualTo(new ClassPathResource("/foo/")); + this.contextLoader.config(WebJars.class).load(context -> { + Map> mappingLocations = getResourceMappingLocations( + context); + assertThat(mappingLocations.get("/webjars/**")).hasSize(1); + assertThat(mappingLocations.get("/webjars/**").get(0)) + .isEqualTo(new ClassPathResource("/foo/")); + }); } @Test public void resourceHandlerMappingOverrideAll() throws Exception { - load(AllResources.class); - Map> mappingLocations = getResourceMappingLocations(); - assertThat(mappingLocations.get("/**")).hasSize(1); - assertThat(mappingLocations.get("/**").get(0)) - .isEqualTo(new ClassPathResource("/foo/")); + this.contextLoader.config(AllResources.class).load(context -> { + Map> mappingLocations = getResourceMappingLocations( + context); + assertThat(mappingLocations.get("/**")).hasSize(1); + assertThat(mappingLocations.get("/**").get(0)) + .isEqualTo(new ClassPathResource("/foo/")); + }); } @Test public void resourceHandlerMappingDisabled() throws Exception { - load("spring.resources.add-mappings:false"); - Map> mappingLocations = getResourceMappingLocations(); - assertThat(mappingLocations.size()).isEqualTo(0); + this.contextLoader.env("spring.resources.add-mappings:false").load(context -> { + Map> mappingLocations = getResourceMappingLocations( + context); + assertThat(mappingLocations.size()).isEqualTo(0); + }); } @Test public void resourceHandlerChainEnabled() throws Exception { - load("spring.resources.chain.enabled:true"); - assertThat(getResourceResolvers("/webjars/**")).hasSize(2); - assertThat(getResourceTransformers("/webjars/**")).hasSize(1); - assertThat(getResourceResolvers("/**")).extractingResultOf("getClass") - .containsOnly(CachingResourceResolver.class, PathResourceResolver.class); - assertThat(getResourceTransformers("/**")).extractingResultOf("getClass") - .containsOnly(CachingResourceTransformer.class); + this.contextLoader.env("spring.resources.chain.enabled:true").load(context -> { + assertThat(getResourceResolvers(context, "/webjars/**")).hasSize(2); + assertThat(getResourceTransformers(context, "/webjars/**")).hasSize(1); + assertThat(getResourceResolvers(context, "/**")) + .extractingResultOf("getClass").containsOnly( + CachingResourceResolver.class, PathResourceResolver.class); + assertThat(getResourceTransformers(context, "/**")) + .extractingResultOf("getClass") + .containsOnly(CachingResourceTransformer.class); + }); } @Test public void resourceHandlerFixedStrategyEnabled() throws Exception { - load("spring.resources.chain.strategy.fixed.enabled:true", - "spring.resources.chain.strategy.fixed.version:test", - "spring.resources.chain.strategy.fixed.paths:/**/*.js"); - assertThat(getResourceResolvers("/webjars/**")).hasSize(3); - assertThat(getResourceTransformers("/webjars/**")).hasSize(2); - assertThat(getResourceResolvers("/**")).extractingResultOf("getClass") - .containsOnly(CachingResourceResolver.class, - VersionResourceResolver.class, PathResourceResolver.class); - assertThat(getResourceTransformers("/**")).extractingResultOf("getClass") - .containsOnly(CachingResourceTransformer.class, - CssLinkResourceTransformer.class); - VersionResourceResolver resolver = (VersionResourceResolver) getResourceResolvers( - "/**").get(1); - assertThat(resolver.getStrategyMap().get("/**/*.js")) - .isInstanceOf(FixedVersionStrategy.class); + this.contextLoader + .env("spring.resources.chain.strategy.fixed.enabled:true", + "spring.resources.chain.strategy.fixed.version:test", + "spring.resources.chain.strategy.fixed.paths:/**/*.js") + .load(context -> { + assertThat(getResourceResolvers(context, "/webjars/**")).hasSize(3); + assertThat(getResourceTransformers(context, "/webjars/**")) + .hasSize(2); + assertThat(getResourceResolvers(context, "/**")) + .extractingResultOf("getClass") + .containsOnly(CachingResourceResolver.class, + VersionResourceResolver.class, + PathResourceResolver.class); + assertThat(getResourceTransformers(context, "/**")) + .extractingResultOf("getClass") + .containsOnly(CachingResourceTransformer.class, + CssLinkResourceTransformer.class); + VersionResourceResolver resolver = (VersionResourceResolver) getResourceResolvers( + context, "/**").get(1); + assertThat(resolver.getStrategyMap().get("/**/*.js")) + .isInstanceOf(FixedVersionStrategy.class); + }); + ; } @Test public void resourceHandlerContentStrategyEnabled() throws Exception { - load("spring.resources.chain.strategy.content.enabled:true", - "spring.resources.chain.strategy.content.paths:/**,/*.png"); - assertThat(getResourceResolvers("/webjars/**")).hasSize(3); - assertThat(getResourceTransformers("/webjars/**")).hasSize(2); - assertThat(getResourceResolvers("/**")).extractingResultOf("getClass") - .containsOnly(CachingResourceResolver.class, - VersionResourceResolver.class, PathResourceResolver.class); - assertThat(getResourceTransformers("/**")).extractingResultOf("getClass") - .containsOnly(CachingResourceTransformer.class, - CssLinkResourceTransformer.class); - VersionResourceResolver resolver = (VersionResourceResolver) getResourceResolvers( - "/**").get(1); - assertThat(resolver.getStrategyMap().get("/*.png")) - .isInstanceOf(ContentVersionStrategy.class); + this.contextLoader + .env("spring.resources.chain.strategy.content.enabled:true", + "spring.resources.chain.strategy.content.paths:/**,/*.png") + .load(context -> { + assertThat(getResourceResolvers(context, "/webjars/**")).hasSize(3); + assertThat(getResourceTransformers(context, "/webjars/**")) + .hasSize(2); + assertThat(getResourceResolvers(context, "/**")) + .extractingResultOf("getClass") + .containsOnly(CachingResourceResolver.class, + VersionResourceResolver.class, + PathResourceResolver.class); + assertThat(getResourceTransformers(context, "/**")) + .extractingResultOf("getClass") + .containsOnly(CachingResourceTransformer.class, + CssLinkResourceTransformer.class); + VersionResourceResolver resolver = (VersionResourceResolver) getResourceResolvers( + context, "/**").get(1); + assertThat(resolver.getStrategyMap().get("/*.png")) + .isInstanceOf(ContentVersionStrategy.class); + }); } @Test - public void resourceHandlerChainCustomized() throws Exception { - load("spring.resources.chain.enabled:true", "spring.resources.chain.cache:false", + public void resourceHandlerChainCustomized() { + this.contextLoader.env("spring.resources.chain.enabled:true", + "spring.resources.chain.cache:false", "spring.resources.chain.strategy.content.enabled:true", "spring.resources.chain.strategy.content.paths:/**,/*.png", "spring.resources.chain.strategy.fixed.enabled:true", @@ -257,128 +274,572 @@ public class WebMvcAutoConfigurationTests { "spring.resources.chain.strategy.fixed.paths:/**/*.js", "spring.resources.chain.html-application-cache:true", "spring.resources.chain.gzipped:true"); - assertThat(getResourceResolvers("/webjars/**")).hasSize(3); - assertThat(getResourceTransformers("/webjars/**")).hasSize(2); - assertThat(getResourceResolvers("/**")).extractingResultOf("getClass") - .containsOnly(VersionResourceResolver.class, GzipResourceResolver.class, - PathResourceResolver.class); - assertThat(getResourceTransformers("/**")).extractingResultOf("getClass") - .containsOnly(CssLinkResourceTransformer.class, - AppCacheManifestTransformer.class); - VersionResourceResolver resolver = (VersionResourceResolver) getResourceResolvers( - "/**").get(0); - assertThat(resolver.getStrategyMap().get("/*.png")) - .isInstanceOf(ContentVersionStrategy.class); - assertThat(resolver.getStrategyMap().get("/**/*.js")) - .isInstanceOf(FixedVersionStrategy.class); + this.contextLoader.load(context -> { + assertThat(getResourceResolvers(context, "/webjars/**")).hasSize(3); + assertThat(getResourceTransformers(context, "/webjars/**")).hasSize(2); + assertThat(getResourceResolvers(context, "/**")) + .extractingResultOf("getClass") + .containsOnly(VersionResourceResolver.class, + GzipResourceResolver.class, PathResourceResolver.class); + assertThat(getResourceTransformers(context, "/**")) + .extractingResultOf("getClass") + .containsOnly(CssLinkResourceTransformer.class, + AppCacheManifestTransformer.class); + VersionResourceResolver resolver = (VersionResourceResolver) getResourceResolvers( + context, "/**").get(0); + Map strategyMap = resolver.getStrategyMap(); + assertThat(strategyMap.get("/*.png")) + .isInstanceOf(ContentVersionStrategy.class); + assertThat(strategyMap.get("/**/*.js")) + .isInstanceOf(FixedVersionStrategy.class); + }); } @Test public void noLocaleResolver() throws Exception { - load(AllResources.class); - this.thrown.expect(NoSuchBeanDefinitionException.class); - this.context.getBean(LocaleResolver.class); + this.contextLoader.load(context -> { + assertThat(context.getBeansOfType(LocaleResolver.class)).isEmpty(); + }); } @Test public void overrideLocale() throws Exception { - load(AllResources.class, "spring.mvc.locale:en_UK", + this.contextLoader.env("spring.mvc.locale:en_UK", "spring.mvc.locale-resolver=fixed"); - // mock request and set user preferred locale - MockHttpServletRequest request = new MockHttpServletRequest(); - request.addPreferredLocale(StringUtils.parseLocaleString("nl_NL")); - request.addHeader(HttpHeaders.ACCEPT_LANGUAGE, "nl_NL"); - LocaleResolver localeResolver = this.context.getBean(LocaleResolver.class); - assertThat(localeResolver).isInstanceOf(FixedLocaleResolver.class); - Locale locale = localeResolver.resolveLocale(request); - // test locale resolver uses fixed locale and not user preferred locale - assertThat(locale.toString()).isEqualTo("en_UK"); + this.contextLoader.load(context -> { + // mock request and set user preferred locale + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addPreferredLocale(StringUtils.parseLocaleString("nl_NL")); + request.addHeader(HttpHeaders.ACCEPT_LANGUAGE, "nl_NL"); + LocaleResolver localeResolver = context.getBean(LocaleResolver.class); + assertThat(localeResolver).isInstanceOf(FixedLocaleResolver.class); + Locale locale = localeResolver.resolveLocale(request); + // test locale resolver uses fixed locale and not user preferred locale + assertThat(locale.toString()).isEqualTo("en_UK"); + }); } @Test public void useAcceptHeaderLocale() { - load(AllResources.class, "spring.mvc.locale:en_UK"); - // mock request and set user preferred locale - MockHttpServletRequest request = new MockHttpServletRequest(); - request.addPreferredLocale(StringUtils.parseLocaleString("nl_NL")); - request.addHeader(HttpHeaders.ACCEPT_LANGUAGE, "nl_NL"); - LocaleResolver localeResolver = this.context.getBean(LocaleResolver.class); - assertThat(localeResolver).isInstanceOf(AcceptHeaderLocaleResolver.class); - Locale locale = localeResolver.resolveLocale(request); - // test locale resolver uses user preferred locale - assertThat(locale.toString()).isEqualTo("nl_NL"); + this.contextLoader.env("spring.mvc.locale:en_UK").load(context -> { + // mock request and set user preferred locale + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addPreferredLocale(StringUtils.parseLocaleString("nl_NL")); + request.addHeader(HttpHeaders.ACCEPT_LANGUAGE, "nl_NL"); + LocaleResolver localeResolver = context.getBean(LocaleResolver.class); + assertThat(localeResolver).isInstanceOf(AcceptHeaderLocaleResolver.class); + Locale locale = localeResolver.resolveLocale(request); + // test locale resolver uses user preferred locale + assertThat(locale.toString()).isEqualTo("nl_NL"); + }); } @Test public void useDefaultLocaleIfAcceptHeaderNoSet() { - load(AllResources.class, "spring.mvc.locale:en_UK"); - // mock request and set user preferred locale - MockHttpServletRequest request = new MockHttpServletRequest(); - LocaleResolver localeResolver = this.context.getBean(LocaleResolver.class); - assertThat(localeResolver).isInstanceOf(AcceptHeaderLocaleResolver.class); - Locale locale = localeResolver.resolveLocale(request); - // test locale resolver uses default locale if no header is set - assertThat(locale.toString()).isEqualTo("en_UK"); + this.contextLoader.env("spring.mvc.locale:en_UK").load(context -> { + // mock request and set user preferred locale + MockHttpServletRequest request = new MockHttpServletRequest(); + LocaleResolver localeResolver = context.getBean(LocaleResolver.class); + assertThat(localeResolver).isInstanceOf(AcceptHeaderLocaleResolver.class); + Locale locale = localeResolver.resolveLocale(request); + // test locale resolver uses default locale if no header is set + assertThat(locale.toString()).isEqualTo("en_UK"); + }); } @Test - public void noDateFormat() throws Exception { - load(AllResources.class); - FormattingConversionService cs = this.context - .getBean(FormattingConversionService.class); - Date date = new DateTime(1988, 6, 25, 20, 30).toDate(); - // formatting cs should use simple toString() - assertThat(cs.convert(date, String.class)).isEqualTo(date.toString()); + public void noDateFormat() { + this.contextLoader.load(context -> { + FormattingConversionService conversionService = context + .getBean(FormattingConversionService.class); + Date date = new DateTime(1988, 6, 25, 20, 30).toDate(); + // formatting conversion service should use simple toString() + assertThat(conversionService.convert(date, String.class)) + .isEqualTo(date.toString()); + }); } @Test - public void overrideDateFormat() throws Exception { - load(AllResources.class, "spring.mvc.date-format:dd*MM*yyyy"); - FormattingConversionService cs = this.context - .getBean(FormattingConversionService.class); - Date date = new DateTime(1988, 6, 25, 20, 30).toDate(); - assertThat(cs.convert(date, String.class)).isEqualTo("25*06*1988"); + public void overrideDateFormat() { + this.contextLoader.env("spring.mvc.date-format:dd*MM*yyyy").load(context -> { + FormattingConversionService conversionService = context + .getBean(FormattingConversionService.class); + Date date = new DateTime(1988, 6, 25, 20, 30).toDate(); + assertThat(conversionService.convert(date, String.class)) + .isEqualTo("25*06*1988"); + }); } @Test - public void noMessageCodesResolver() throws Exception { - load(AllResources.class); - assertThat(this.context.getBean(WebMvcAutoConfigurationAdapter.class) - .getMessageCodesResolver()).isNull(); + public void noMessageCodesResolver() { + this.contextLoader.load(context -> { + assertThat(context.getBean(WebMvcAutoConfigurationAdapter.class) + .getMessageCodesResolver()).isNull(); + }); } @Test - public void overrideMessageCodesFormat() throws Exception { - load(AllResources.class, - "spring.mvc.messageCodesResolverFormat:POSTFIX_ERROR_CODE"); - assertThat(this.context.getBean(WebMvcAutoConfigurationAdapter.class) - .getMessageCodesResolver()).isNotNull(); + public void overrideMessageCodesFormat() { + this.contextLoader + .env("spring.mvc.messageCodesResolverFormat:POSTFIX_ERROR_CODE"); + this.contextLoader.load(context -> { + assertThat(context.getBean(WebMvcAutoConfigurationAdapter.class) + .getMessageCodesResolver()).isNotNull(); + }); } - protected Map> getFaviconMappingLocations() - throws IllegalAccessException { - HandlerMapping mapping = (HandlerMapping) this.context + @Test + public void ignoreDefaultModelOnRedirectIsTrue() { + this.contextLoader.load(context -> { + RequestMappingHandlerAdapter adapter = context + .getBean(RequestMappingHandlerAdapter.class); + assertThat(adapter).extracting("ignoreDefaultModelOnRedirect") + .containsExactly(true); + }); + } + + @Test + public void overrideIgnoreDefaultModelOnRedirect() { + this.contextLoader.env("spring.mvc.ignore-default-model-on-redirect:false"); + this.contextLoader.load(context -> { + RequestMappingHandlerAdapter adapter = context + .getBean(RequestMappingHandlerAdapter.class); + assertThat(adapter).extracting("ignoreDefaultModelOnRedirect") + .containsExactly(false); + }); + } + + @Test + public void customViewResolver() { + this.contextLoader.config(CustomViewResolver.class).load(context -> { + assertThat(context.getBean("viewResolver")) + .isInstanceOf(MyViewResolver.class); + }); + } + + @Test + public void customContentNegotiatingViewResolver() throws Exception { + this.contextLoader.config(CustomContentNegotiatingViewResolver.class); + this.contextLoader.load(context -> { + Map beans = context + .getBeansOfType(ContentNegotiatingViewResolver.class); + assertThat(beans.size()).isEqualTo(1); + assertThat(beans.keySet().iterator().next()).isEqualTo("myViewResolver"); + }); + } + + @Test + public void faviconMapping() { + this.contextLoader.load(context -> { + assertThat(context.getBeansOfType(ResourceHttpRequestHandler.class) + .get("faviconRequestHandler")).isNotNull(); + assertThat(context.getBeansOfType(SimpleUrlHandlerMapping.class) + .get("faviconHandlerMapping")).isNotNull(); + Map> mappingLocations = getFaviconMappingLocations( + context); + assertThat(mappingLocations.get("/**/favicon.ico")).hasSize(6); + }); + } + + @Test + public void faviconMappingUsesStaticLocations() { + this.contextLoader.env("spring.resources.static-locations=classpath:/static"); + this.contextLoader.load(context -> { + assertThat(getFaviconMappingLocations(context).get("/**/favicon.ico")) + .hasSize(2); + }); + } + + @Test + public void faviconMappingDisabled() throws IllegalAccessException { + this.contextLoader.env("spring.mvc.favicon.enabled:false").load(context -> { + assertThat(context.getBeansOfType(ResourceHttpRequestHandler.class) + .get("faviconRequestHandler")).isNull(); + assertThat(context.getBeansOfType(SimpleUrlHandlerMapping.class) + .get("faviconHandlerMapping")).isNull(); + }); + } + + @Test + public void defaultAsyncRequestTimeout() throws Exception { + this.contextLoader.load(context -> { + RequestMappingHandlerAdapter adapter = context + .getBean(RequestMappingHandlerAdapter.class); + assertThat(ReflectionTestUtils.getField(adapter, "asyncRequestTimeout")) + .isNull(); + }); + } + + @Test + public void customAsyncRequestTimeout() throws Exception { + this.contextLoader.env("spring.mvc.async.request-timeout:12345").load(context -> { + RequestMappingHandlerAdapter adapter = context + .getBean(RequestMappingHandlerAdapter.class); + assertThat(ReflectionTestUtils.getField(adapter, "asyncRequestTimeout")) + .isEqualTo(12345L); + }); + } + + @Test + public void customMediaTypes() throws Exception { + this.contextLoader.env("spring.mvc.mediaTypes.yaml:text/yaml").load(context -> { + RequestMappingHandlerAdapter adapter = context + .getBean(RequestMappingHandlerAdapter.class); + ContentNegotiationManager contentNegotiationManager = (ContentNegotiationManager) ReflectionTestUtils + .getField(adapter, "contentNegotiationManager"); + assertThat(contentNegotiationManager.getAllFileExtensions()).contains("yaml"); + }); + } + + @Test + public void httpPutFormContentFilterIsAutoConfigured() { + this.contextLoader.load(context -> { + assertThat(context.getBeansOfType(OrderedHttpPutFormContentFilter.class)) + .hasSize(1); + }); + } + + @Test + public void httpPutFormContentFilterCanBeOverridden() { + this.contextLoader.config(CustomHttpPutFormContentFilter.class).load(context -> { + assertThat(context.getBeansOfType(OrderedHttpPutFormContentFilter.class)) + .hasSize(0); + assertThat(context.getBeansOfType(HttpPutFormContentFilter.class)).hasSize(1); + }); + } + + @Test + public void httpPutFormContentFilterCanBeDisabled() throws Exception { + this.contextLoader.env("spring.mvc.formcontent.putfilter.enabled=false"); + this.contextLoader.load(context -> { + assertThat(context.getBeansOfType(HttpPutFormContentFilter.class)).isEmpty(); + }); + } + + @Test + public void customConfigurableWebBindingInitializer() { + this.contextLoader.config(CustomConfigurableWebBindingInitializer.class); + this.contextLoader.load(context -> { + assertThat(context.getBean(RequestMappingHandlerAdapter.class) + .getWebBindingInitializer()) + .isInstanceOf(CustomWebBindingInitializer.class); + }); + } + + @Test + public void customRequestMappingHandlerMapping() { + this.contextLoader.config(CustomRequestMappingHandlerMapping.class); + this.contextLoader.load(context -> { + assertThat(context.getBean(RequestMappingHandlerMapping.class)) + .isInstanceOf(MyRequestMappingHandlerMapping.class); + }); + } + + @Test + public void customRequestMappingHandlerAdapter() { + this.contextLoader.config(CustomRequestMappingHandlerAdapter.class); + this.contextLoader.load(context -> { + assertThat(context.getBean(RequestMappingHandlerAdapter.class)) + .isInstanceOf(MyRequestMappingHandlerAdapter.class); + }); + } + + @Test + public void multipleWebMvcRegistrations() { + this.contextLoader.config(MultipleWebMvcRegistrations.class).load(context -> { + assertThat(context.getBean(RequestMappingHandlerMapping.class)) + .isNotInstanceOf(MyRequestMappingHandlerMapping.class); + assertThat(context.getBean(RequestMappingHandlerAdapter.class)) + .isNotInstanceOf(MyRequestMappingHandlerAdapter.class); + }); + } + + @Test + public void defaultLogResolvedException() { + this.contextLoader.load(context -> { + assertExceptionResolverWarnLoggers(context, + warnLogger -> assertThat(warnLogger).isNull()); + }); + } + + @Test + public void customLogResolvedException() { + this.contextLoader.env("spring.mvc.log-resolved-exception:true").load(context -> { + assertExceptionResolverWarnLoggers(context, + warnLogger -> assertThat(warnLogger).isNotNull()); + }); + } + + @Test + public void welcomePageMappingProducesNotFoundResponseWhenThereIsNoWelcomePage() { + this.contextLoader + .env("spring.resources.static-locations:classpath:/no-welcome-page/"); + this.contextLoader.webServlet().load(context -> { + assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class)) + .hasSize(1); + // TODO This cast is ugly. Fix it with generics and ContextLoader subclasses + MockMvcBuilders.webAppContextSetup((WebApplicationContext) context).build() + .perform(get("/").accept(MediaType.TEXT_HTML)) + .andExpect(status().isNotFound()); + }); + } + + @Test + public void welcomePageRootHandlerIsNotRegisteredWhenStaticPathPatternIsNotSlashStarStar() { + this.contextLoader.env( + "spring.resources.static-locations:classpath:/welcome-page/", + "spring.mvc.static-path-pattern:/foo/**"); + this.contextLoader.load(context -> { + WelcomePageHandlerMapping welcomePageHandlerMapping = context + .getBean(WelcomePageHandlerMapping.class); + assertThat(welcomePageHandlerMapping.getRootHandler()).isNull(); + }); + } + + @Test + public void welcomePageMappingHandlesRequestsThatAcceptTextHtml() { + this.contextLoader + .env("spring.resources.static-locations:classpath:/welcome-page/"); + this.contextLoader.load(context -> { + assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class)) + .hasSize(1); + MockMvc mockMvc = MockMvcBuilders + .webAppContextSetup((WebApplicationContext) context).build(); + mockMvc.perform(get("/").accept(MediaType.TEXT_HTML)) + .andExpect(status().isOk()).andExpect(forwardedUrl("index.html")); + mockMvc.perform(get("/").accept("*/*")).andExpect(status().isOk()) + .andExpect(forwardedUrl("index.html")); + }); + } + + @Test + public void welcomePageMappingDoesNotHandleRequestsThatDoNotAcceptTextHtml() { + this.contextLoader + .env("spring.resources.static-locations:classpath:/welcome-page/"); + this.contextLoader.load(context -> { + assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class)) + .hasSize(1); + MockMvc mockMvc = MockMvcBuilders + .webAppContextSetup((WebApplicationContext) context).build(); + mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isNotFound()); + }); + } + + @Test + public void welcomePageMappingHandlesRequestsWithNoAcceptHeader() { + this.contextLoader + .env("spring.resources.static-locations:classpath:/welcome-page/"); + this.contextLoader.load(context -> { + assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class)) + .hasSize(1); + MockMvc mockMvc = MockMvcBuilders + .webAppContextSetup((WebApplicationContext) context).build(); + mockMvc.perform(get("/")).andExpect(status().isOk()) + .andExpect(forwardedUrl("index.html")); + }); + } + + @Test + public void welcomePageMappingHandlesRequestsWithEmptyAcceptHeader() + throws Exception { + this.contextLoader + .env("spring.resources.static-locations:classpath:/welcome-page/"); + this.contextLoader.load(context -> { + assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class)) + .hasSize(1); + MockMvc mockMvc = MockMvcBuilders + .webAppContextSetup((WebApplicationContext) context).build(); + mockMvc.perform(get("/").header(HttpHeaders.ACCEPT, "")) + .andExpect(status().isOk()).andExpect(forwardedUrl("index.html")); + }); + } + + @Test + public void welcomePageMappingWorksWithNoTrailingSlashOnResourceLocation() + throws Exception { + this.contextLoader + .env("spring.resources.static-locations:classpath:/welcome-page"); + this.contextLoader.load(context -> { + assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class)) + .hasSize(1); + MockMvc mockMvc = MockMvcBuilders + .webAppContextSetup((WebApplicationContext) context).build(); + mockMvc.perform(get("/").accept(MediaType.TEXT_HTML)) + .andExpect(status().isOk()).andExpect(forwardedUrl("index.html")); + }); + + } + + @Test + public void validatorWhenNoValidatorShouldUseDefault() { + this.contextLoader.load(context -> { + assertThat(context.getBeansOfType(ValidatorFactory.class)).isEmpty(); + assertThat(context.getBeansOfType(javax.validation.Validator.class)) + .isEmpty(); + String[] springValidatorBeans = context.getBeanNamesForType(Validator.class); + assertThat(springValidatorBeans).containsExactly("mvcValidator"); + }); + } + + @Test + public void validatorWhenNoCustomizationShouldUseAutoConfigured() { + this.contextLoader.autoConfigFirst(ValidationAutoConfiguration.class); + this.contextLoader.load(context -> { + String[] jsrValidatorBeans = context + .getBeanNamesForType(javax.validation.Validator.class); + String[] springValidatorBeans = context.getBeanNamesForType(Validator.class); + assertThat(jsrValidatorBeans).containsExactly("defaultValidator"); + assertThat(springValidatorBeans).containsExactly("defaultValidator", + "mvcValidator"); + Validator validator = context.getBean("mvcValidator", Validator.class); + assertThat(validator).isInstanceOf(ValidatorAdapter.class); + Object defaultValidator = context.getBean("defaultValidator"); + assertThat(((ValidatorAdapter) validator).getTarget()) + .isSameAs(defaultValidator); + // Primary Spring validator is the one used by MVC behind the scenes + assertThat(context.getBean(Validator.class)).isEqualTo(defaultValidator); + }); + } + + @Test + public void validatorWithConfigurerShouldUseSpringValidator() { + this.contextLoader.config(MvcValidator.class).load(context -> { + assertThat(context.getBeansOfType(ValidatorFactory.class)).isEmpty(); + assertThat(context.getBeansOfType(javax.validation.Validator.class)) + .isEmpty(); + String[] springValidatorBeans = context.getBeanNamesForType(Validator.class); + assertThat(springValidatorBeans).containsExactly("mvcValidator"); + assertThat(context.getBean("mvcValidator")) + .isSameAs(context.getBean(MvcValidator.class).validator); + }); + } + + @Test + public void validatorWithConfigurerDoesNotExposeJsr303() { + this.contextLoader.config(MvcJsr303Validator.class).load(context -> { + assertThat(context.getBeansOfType(ValidatorFactory.class)).isEmpty(); + assertThat(context.getBeansOfType(javax.validation.Validator.class)) + .isEmpty(); + String[] springValidatorBeans = context.getBeanNamesForType(Validator.class); + assertThat(springValidatorBeans).containsExactly("mvcValidator"); + Validator validator = context.getBean("mvcValidator", Validator.class); + assertThat(validator).isInstanceOf(ValidatorAdapter.class); + assertThat(((ValidatorAdapter) validator).getTarget()) + .isSameAs(context.getBean(MvcJsr303Validator.class).validator); + }); + } + + @Test + public void validatorWithConfigurerTakesPrecedence() { + this.contextLoader.autoConfigFirst(ValidationAutoConfiguration.class) + .config(MvcValidator.class); + this.contextLoader.load(context -> { + assertThat(context.getBeansOfType(ValidatorFactory.class)).hasSize(1); + assertThat(context.getBeansOfType(javax.validation.Validator.class)) + .hasSize(1); + String[] springValidatorBeans = context.getBeanNamesForType(Validator.class); + assertThat(springValidatorBeans).containsExactly("defaultValidator", + "mvcValidator"); + assertThat(context.getBean("mvcValidator")) + .isSameAs(context.getBean(MvcValidator.class).validator); + // Primary Spring validator is the auto-configured one as the MVC one has been + // customized via a WebMvcConfigurer + assertThat(context.getBean(Validator.class)) + .isEqualTo(context.getBean("defaultValidator")); + }); + + } + + @Test + public void validatorWithCustomSpringValidatorIgnored() { + this.contextLoader.autoConfigFirst(ValidationAutoConfiguration.class) + .config(CustomSpringValidator.class); + this.contextLoader.load(context -> { + String[] jsrValidatorBeans = context + .getBeanNamesForType(javax.validation.Validator.class); + String[] springValidatorBeans = context.getBeanNamesForType(Validator.class); + assertThat(jsrValidatorBeans).containsExactly("defaultValidator"); + assertThat(springValidatorBeans).containsExactly("customSpringValidator", + "defaultValidator", "mvcValidator"); + Validator validator = context.getBean("mvcValidator", Validator.class); + assertThat(validator).isInstanceOf(ValidatorAdapter.class); + Object defaultValidator = context.getBean("defaultValidator"); + assertThat(((ValidatorAdapter) validator).getTarget()) + .isSameAs(defaultValidator); + // Primary Spring validator is the one used by MVC behind the scenes + assertThat(context.getBean(Validator.class)).isEqualTo(defaultValidator); + }); + + } + + @Test + public void validatorWithCustomJsr303ValidatorExposedAsSpringValidator() { + this.contextLoader.autoConfigFirst(ValidationAutoConfiguration.class) + .config(CustomJsr303Validator.class); + this.contextLoader.load(context -> { + assertThat(context.getBeansOfType(ValidatorFactory.class)).isEmpty(); + String[] jsrValidatorBeans = context + .getBeanNamesForType(javax.validation.Validator.class); + String[] springValidatorBeans = context.getBeanNamesForType(Validator.class); + assertThat(jsrValidatorBeans).containsExactly("customJsr303Validator"); + assertThat(springValidatorBeans).containsExactly("mvcValidator"); + Validator validator = context.getBean(Validator.class); + assertThat(validator).isInstanceOf(ValidatorAdapter.class); + Validator target = ((ValidatorAdapter) validator).getTarget(); + assertThat(ReflectionTestUtils.getField(target, "targetValidator")) + .isSameAs(context.getBean("customJsr303Validator")); + }); + } + + @Test + public void httpMessageConverterThatUsesConversionServiceDoesNotCreateACycle() { + // TODO load(ContextConsumer...) or load() + this.contextLoader.config(CustomHttpMessageConverter.class).load(context -> { + }); + } + + private void assertExceptionResolverWarnLoggers(ApplicationContext context, + Consumer warnLogger) { + HandlerExceptionResolver exceptionResolver = context + .getBean(HandlerExceptionResolver.class); + assertThat(exceptionResolver) + .isInstanceOf(HandlerExceptionResolverComposite.class); + List delegates = ((HandlerExceptionResolverComposite) exceptionResolver) + .getExceptionResolvers(); + for (HandlerExceptionResolver delegate : delegates) { + if (delegate instanceof AbstractHandlerExceptionResolver) { + warnLogger.accept(ReflectionTestUtils.getField(delegate, "warnLogger")); + } + } + } + + protected Map> getFaviconMappingLocations( + ApplicationContext context) { + HandlerMapping mapping = (HandlerMapping) context .getBean("faviconHandlerMapping"); return getMappingLocations(mapping); } - protected Map> getResourceMappingLocations() - throws IllegalAccessException { - HandlerMapping mapping = (HandlerMapping) this.context + protected Map> getResourceMappingLocations( + ApplicationContext context) throws IllegalAccessException { + HandlerMapping mapping = (HandlerMapping) context .getBean("resourceHandlerMapping"); return getMappingLocations(mapping); } - protected List getResourceResolvers(String mapping) { - SimpleUrlHandlerMapping handler = (SimpleUrlHandlerMapping) this.context + protected List getResourceResolvers(ApplicationContext context, + String mapping) { + SimpleUrlHandlerMapping handler = (SimpleUrlHandlerMapping) context .getBean("resourceHandlerMapping"); ResourceHttpRequestHandler resourceHandler = (ResourceHttpRequestHandler) handler .getHandlerMap().get(mapping); return resourceHandler.getResourceResolvers(); } - protected List getResourceTransformers(String mapping) { - SimpleUrlHandlerMapping handler = (SimpleUrlHandlerMapping) this.context + protected List getResourceTransformers( + ApplicationContext context, String mapping) { + SimpleUrlHandlerMapping handler = (SimpleUrlHandlerMapping) context .getBean("resourceHandlerMapping"); ResourceHttpRequestHandler resourceHandler = (ResourceHttpRequestHandler) handler .getHandlerMap().get(mapping); @@ -386,414 +847,17 @@ public class WebMvcAutoConfigurationTests { } @SuppressWarnings("unchecked") - protected Map> getMappingLocations(HandlerMapping mapping) - throws IllegalAccessException { + protected Map> getMappingLocations(HandlerMapping mapping) { Map> mappingLocations = new LinkedHashMap<>(); if (mapping instanceof SimpleUrlHandlerMapping) { - Field locationsField = ReflectionUtils - .findField(ResourceHttpRequestHandler.class, "locations"); - locationsField.setAccessible(true); - for (Map.Entry entry : ((SimpleUrlHandlerMapping) mapping) - .getHandlerMap().entrySet()) { - ResourceHttpRequestHandler handler = (ResourceHttpRequestHandler) entry - .getValue(); - mappingLocations.put(entry.getKey(), - (List) locationsField.get(handler)); - } + ((SimpleUrlHandlerMapping) mapping).getHandlerMap().forEach((key, value) -> { + mappingLocations.put(key, (List) ReflectionTestUtils + .getField(value, "locations")); + }); } return mappingLocations; } - @Test - public void ignoreDefaultModelOnRedirectIsTrue() throws Exception { - load(); - RequestMappingHandlerAdapter adapter = this.context - .getBean(RequestMappingHandlerAdapter.class); - assertThat(adapter).extracting("ignoreDefaultModelOnRedirect") - .containsExactly(true); - } - - @Test - public void overrideIgnoreDefaultModelOnRedirect() throws Exception { - this.context = new AnnotationConfigServletWebServerApplicationContext(); - TestPropertyValues.of("spring.mvc.ignore-default-model-on-redirect:false") - .applyTo(this.context); - this.context.register(Config.class, WebMvcAutoConfiguration.class, - HttpMessageConvertersAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class); - this.context.refresh(); - RequestMappingHandlerAdapter adapter = this.context - .getBean(RequestMappingHandlerAdapter.class); - assertThat(adapter).extracting("ignoreDefaultModelOnRedirect") - .containsExactly(false); - } - - @Test - public void customViewResolver() throws Exception { - load(CustomViewResolver.class); - assertThat(this.context.getBean("viewResolver")) - .isInstanceOf(MyViewResolver.class); - } - - @Test - public void customContentNegotiatingViewResolver() throws Exception { - load(CustomContentNegotiatingViewResolver.class); - Map beans = this.context - .getBeansOfType(ContentNegotiatingViewResolver.class); - assertThat(beans.size()).isEqualTo(1); - assertThat(beans.keySet().iterator().next()).isEqualTo("myViewResolver"); - } - - @Test - public void faviconMapping() throws IllegalAccessException { - load(); - assertThat(this.context.getBeansOfType(ResourceHttpRequestHandler.class) - .get("faviconRequestHandler")).isNotNull(); - assertThat(this.context.getBeansOfType(SimpleUrlHandlerMapping.class) - .get("faviconHandlerMapping")).isNotNull(); - Map> mappingLocations = getFaviconMappingLocations(); - assertThat(mappingLocations.get("/**/favicon.ico")).hasSize(6); - } - - @Test - public void faviconMappingUsesStaticLocations() throws IllegalAccessException { - load("spring.resources.static-locations=classpath:/static"); - Map> mappingLocations = getFaviconMappingLocations(); - assertThat(mappingLocations.get("/**/favicon.ico")).hasSize(2); - } - - @Test - public void faviconMappingDisabled() throws IllegalAccessException { - load("spring.mvc.favicon.enabled:false"); - assertThat(this.context.getBeansOfType(ResourceHttpRequestHandler.class) - .get("faviconRequestHandler")).isNull(); - assertThat(this.context.getBeansOfType(SimpleUrlHandlerMapping.class) - .get("faviconHandlerMapping")).isNull(); - } - - @Test - public void defaultAsyncRequestTimeout() throws Exception { - load(); - RequestMappingHandlerAdapter adapter = this.context - .getBean(RequestMappingHandlerAdapter.class); - assertThat(ReflectionTestUtils.getField(adapter, "asyncRequestTimeout")).isNull(); - } - - @Test - public void customAsyncRequestTimeout() throws Exception { - load("spring.mvc.async.request-timeout:123456"); - RequestMappingHandlerAdapter adapter = this.context - .getBean(RequestMappingHandlerAdapter.class); - Object actual = ReflectionTestUtils.getField(adapter, "asyncRequestTimeout"); - assertThat(actual).isEqualTo(123456L); - } - - @Test - public void customMediaTypes() throws Exception { - load("spring.mvc.mediaTypes.yaml:text/yaml"); - RequestMappingHandlerAdapter adapter = this.context - .getBean(RequestMappingHandlerAdapter.class); - ContentNegotiationManager actual = (ContentNegotiationManager) ReflectionTestUtils - .getField(adapter, "contentNegotiationManager"); - assertThat(actual.getAllFileExtensions().contains("yaml")).isTrue(); - } - - @Test - public void httpPutFormContentFilterIsAutoConfigured() { - load(); - assertThat(this.context.getBeansOfType(OrderedHttpPutFormContentFilter.class)) - .hasSize(1); - } - - @Test - public void httpPutFormContentFilterCanBeOverridden() { - load(CustomHttpPutFormContentFilter.class); - assertThat(this.context.getBeansOfType(OrderedHttpPutFormContentFilter.class)) - .hasSize(0); - assertThat(this.context.getBeansOfType(HttpPutFormContentFilter.class)) - .hasSize(1); - } - - @Test - public void httpPutFormContentFilterCanBeDisabled() throws Exception { - load((Class) null, "spring.mvc.formcontent.putfilter.enabled=false"); - assertThat(this.context.getBeansOfType(HttpPutFormContentFilter.class)).isEmpty(); - } - - @Test - public void customConfigurableWebBindingInitializer() { - load(CustomConfigurableWebBindingInitializer.class); - assertThat(this.context.getBean(RequestMappingHandlerAdapter.class) - .getWebBindingInitializer()) - .isInstanceOf(CustomWebBindingInitializer.class); - } - - @Test - public void customRequestMappingHandlerMapping() { - load(CustomRequestMappingHandlerMapping.class); - assertThat(this.context.getBean(RequestMappingHandlerMapping.class)) - .isInstanceOf(MyRequestMappingHandlerMapping.class); - } - - @Test - public void customRequestMappingHandlerAdapter() { - load(CustomRequestMappingHandlerAdapter.class); - assertThat(this.context.getBean(RequestMappingHandlerAdapter.class)) - .isInstanceOf(MyRequestMappingHandlerAdapter.class); - } - - @Test - public void multipleWebMvcRegistrations() { - load(MultipleWebMvcRegistrations.class); - assertThat(this.context.getBean(RequestMappingHandlerMapping.class)) - .isNotInstanceOf(MyRequestMappingHandlerMapping.class); - assertThat(this.context.getBean(RequestMappingHandlerAdapter.class)) - .isNotInstanceOf(MyRequestMappingHandlerAdapter.class); - } - - @Test - public void defaultLogResolvedException() { - load(); - testLogResolvedExceptionCustomization(false); - } - - @Test - public void customLogResolvedException() { - load("spring.mvc.log-resolved-exception:true"); - testLogResolvedExceptionCustomization(true); - } - - @Test - public void welcomePageMappingProducesNotFoundResponseWhenThereIsNoWelcomePage() - throws Exception { - load("spring.resources.static-locations:classpath:/no-welcome-page/"); - assertThat(this.context.getBeansOfType(WelcomePageHandlerMapping.class)) - .hasSize(1); - MockMvcBuilders.webAppContextSetup(this.context).build() - .perform(get("/").accept(MediaType.TEXT_HTML)) - .andExpect(status().isNotFound()); - } - - @Test - public void welcomePageRootHandlerIsNotRegisteredWhenStaticPathPatternIsNotSlashStarStar() { - load("spring.resources.static-locations:classpath:/welcome-page/", - "spring.mvc.static-path-pattern:/foo/**"); - WelcomePageHandlerMapping welcomePageHandlerMapping = this.context - .getBean(WelcomePageHandlerMapping.class); - assertThat(welcomePageHandlerMapping.getRootHandler()).isNull(); - } - - @Test - public void welcomePageMappingHandlesRequestsThatAcceptTextHtml() throws Exception { - load("spring.resources.static-locations:classpath:/welcome-page/"); - assertThat(this.context.getBeansOfType(WelcomePageHandlerMapping.class)) - .hasSize(1); - MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build(); - mockMvc.perform(get("/").accept(MediaType.TEXT_HTML)).andExpect(status().isOk()) - .andExpect(forwardedUrl("index.html")); - mockMvc.perform(get("/").accept("*/*")).andExpect(status().isOk()) - .andExpect(forwardedUrl("index.html")); - } - - @Test - public void welcomePageMappingDoesNotHandleRequestsThatDoNotAcceptTextHtml() - throws Exception { - load("spring.resources.static-locations:classpath:/welcome-page/"); - assertThat(this.context.getBeansOfType(WelcomePageHandlerMapping.class)) - .hasSize(1); - MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build(); - mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isNotFound()); - } - - @Test - public void welcomePageMappingHandlesRequestsWithNoAcceptHeader() throws Exception { - load("spring.resources.static-locations:classpath:/welcome-page/"); - assertThat(this.context.getBeansOfType(WelcomePageHandlerMapping.class)) - .hasSize(1); - MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build(); - mockMvc.perform(get("/")).andExpect(status().isOk()) - .andExpect(forwardedUrl("index.html")); - } - - @Test - public void welcomePageMappingHandlesRequestsWithEmptyAcceptHeader() - throws Exception { - load("spring.resources.static-locations:classpath:/welcome-page/"); - assertThat(this.context.getBeansOfType(WelcomePageHandlerMapping.class)) - .hasSize(1); - MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build(); - mockMvc.perform(get("/").header(HttpHeaders.ACCEPT, "")) - .andExpect(status().isOk()).andExpect(forwardedUrl("index.html")); - } - - @Test - public void welcomePageMappingWorksWithNoTrailingSlashOnResourceLocation() - throws Exception { - load("spring.resources.static-locations:classpath:/welcome-page"); - assertThat(this.context.getBeansOfType(WelcomePageHandlerMapping.class)) - .hasSize(1); - MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build(); - mockMvc.perform(get("/").accept(MediaType.TEXT_HTML)).andExpect(status().isOk()) - .andExpect(forwardedUrl("index.html")); - } - - private void testLogResolvedExceptionCustomization(final boolean expected) { - HandlerExceptionResolver exceptionResolver = this.context - .getBean(HandlerExceptionResolver.class); - assertThat(exceptionResolver) - .isInstanceOf(HandlerExceptionResolverComposite.class); - List delegates = ((HandlerExceptionResolverComposite) exceptionResolver) - .getExceptionResolvers(); - for (HandlerExceptionResolver delegate : delegates) { - if (delegate instanceof AbstractHandlerMethodAdapter) { - assertThat( - new DirectFieldAccessor(delegate).getPropertyValue("warnLogger")) - .is(new Condition() { - @Override - public boolean matches(Object value) { - return (expected ? value != null : value == null); - } - }); - } - } - } - - @Test - public void validatorWhenNoValidatorShouldUseDefault() { - load(null, new Class[] { ValidationAutoConfiguration.class }); - assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty(); - assertThat(this.context.getBeansOfType(javax.validation.Validator.class)) - .isEmpty(); - String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class); - assertThat(springValidatorBeans).containsExactly("mvcValidator"); - } - - @Test - public void validatorWhenNoCustomizationShouldUseAutoConfigured() { - load(); - String[] jsrValidatorBeans = this.context - .getBeanNamesForType(javax.validation.Validator.class); - String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class); - assertThat(jsrValidatorBeans).containsExactly("defaultValidator"); - assertThat(springValidatorBeans).containsExactly("defaultValidator", - "mvcValidator"); - Validator validator = this.context.getBean("mvcValidator", Validator.class); - assertThat(validator).isInstanceOf(ValidatorAdapter.class); - Object defaultValidator = this.context.getBean("defaultValidator"); - assertThat(((ValidatorAdapter) validator).getTarget()).isSameAs(defaultValidator); - // Primary Spring validator is the one used by MVC behind the scenes - assertThat(this.context.getBean(Validator.class)).isEqualTo(defaultValidator); - } - - @Test - public void validatorWithConfigurerShouldUseSpringValidator() { - load(MvcValidator.class, new Class[] { ValidationAutoConfiguration.class }); - assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty(); - assertThat(this.context.getBeansOfType(javax.validation.Validator.class)) - .isEmpty(); - String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class); - assertThat(springValidatorBeans).containsExactly("mvcValidator"); - assertThat(this.context.getBean("mvcValidator")) - .isSameAs(this.context.getBean(MvcValidator.class).validator); - } - - @Test - public void validatorWithConfigurerDoesNotExposeJsr303() { - load(MvcJsr303Validator.class, - new Class[] { ValidationAutoConfiguration.class }); - assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty(); - assertThat(this.context.getBeansOfType(javax.validation.Validator.class)) - .isEmpty(); - String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class); - assertThat(springValidatorBeans).containsExactly("mvcValidator"); - Validator validator = this.context.getBean("mvcValidator", Validator.class); - assertThat(validator).isInstanceOf(ValidatorAdapter.class); - assertThat(((ValidatorAdapter) validator).getTarget()) - .isSameAs(this.context.getBean(MvcJsr303Validator.class).validator); - } - - @Test - public void validatorWithConfigurerTakesPrecedence() { - load(MvcValidator.class); - assertThat(this.context.getBeansOfType(ValidatorFactory.class)).hasSize(1); - assertThat(this.context.getBeansOfType(javax.validation.Validator.class)) - .hasSize(1); - String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class); - assertThat(springValidatorBeans).containsExactly("defaultValidator", - "mvcValidator"); - assertThat(this.context.getBean("mvcValidator")) - .isSameAs(this.context.getBean(MvcValidator.class).validator); - // Primary Spring validator is the auto-configured one as the MVC one has been - // customized via a WebMvcConfigurer - assertThat(this.context.getBean(Validator.class)) - .isEqualTo(this.context.getBean("defaultValidator")); - } - - @Test - public void validatorWithCustomSpringValidatorIgnored() { - load(CustomSpringValidator.class); - String[] jsrValidatorBeans = this.context - .getBeanNamesForType(javax.validation.Validator.class); - String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class); - assertThat(jsrValidatorBeans).containsExactly("defaultValidator"); - assertThat(springValidatorBeans).containsExactly("customSpringValidator", - "defaultValidator", "mvcValidator"); - Validator validator = this.context.getBean("mvcValidator", Validator.class); - assertThat(validator).isInstanceOf(ValidatorAdapter.class); - Object defaultValidator = this.context.getBean("defaultValidator"); - assertThat(((ValidatorAdapter) validator).getTarget()).isSameAs(defaultValidator); - // Primary Spring validator is the one used by MVC behind the scenes - assertThat(this.context.getBean(Validator.class)).isEqualTo(defaultValidator); - } - - @Test - public void validatorWithCustomJsr303ValidatorExposedAsSpringValidator() { - load(CustomJsr303Validator.class); - assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty(); - String[] jsrValidatorBeans = this.context - .getBeanNamesForType(javax.validation.Validator.class); - String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class); - assertThat(jsrValidatorBeans).containsExactly("customJsr303Validator"); - assertThat(springValidatorBeans).containsExactly("mvcValidator"); - Validator validator = this.context.getBean(Validator.class); - assertThat(validator).isInstanceOf(ValidatorAdapter.class); - Validator target = ((ValidatorAdapter) validator).getTarget(); - assertThat(new DirectFieldAccessor(target).getPropertyValue("targetValidator")) - .isSameAs(this.context.getBean("customJsr303Validator")); - } - - @Test - public void httpMessageConverterThatUsesConversionServiceDoesNotCreateACycle() { - load(CustomHttpMessageConverter.class); - } - - private void load(Class config, String... environment) { - load(config, null, environment); - } - - private void load(Class config, Class[] exclude, String... environment) { - this.context = new AnnotationConfigServletWebServerApplicationContext(); - TestPropertyValues.of(environment).applyTo(this.context); - List> configClasses = new ArrayList<>(); - if (config != null) { - configClasses.add(config); - } - configClasses.addAll(Arrays.asList(Config.class, - ValidationAutoConfiguration.class, WebMvcAutoConfiguration.class, - HttpMessageConvertersAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class)); - if (!ObjectUtils.isEmpty(exclude)) { - configClasses.removeAll(Arrays.asList(exclude)); - } - this.context.register(configClasses.toArray(new Class[configClasses.size()])); - this.context.refresh(); - } - - private void load(String... environment) { - load(null, environment); - } - @Configuration protected static class ViewConfig { diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/webservices/WebServicesAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/webservices/WebServicesAutoConfigurationTests.java index d549e0d429..90175a9716 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/webservices/WebServicesAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/webservices/WebServicesAutoConfigurationTests.java @@ -16,17 +16,14 @@ package org.springframework.boot.autoconfigure.webservices; -import org.junit.After; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.springframework.beans.factory.BeanCreationException; -import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.boot.test.context.ContextLoader; import org.springframework.boot.web.servlet.ServletRegistrationBean; -import org.springframework.mock.web.MockServletContext; import org.springframework.test.util.ReflectionTestUtils; -import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import static org.assertj.core.api.Assertions.assertThat; @@ -35,79 +32,73 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Vedran Pavic * @author Stephane Nicoll + * @author Andy Wilkinson */ public class WebServicesAutoConfigurationTests { + private final ContextLoader contextLoader = new ContextLoader().webServlet() + .autoConfig(WebServicesAutoConfiguration.class); + @Rule public ExpectedException thrown = ExpectedException.none(); - private AnnotationConfigWebApplicationContext context; - - @After - public void close() { - if (this.context != null) { - this.context.close(); - } - } - @Test public void defaultConfiguration() { - load(WebServicesAutoConfiguration.class); - assertThat(this.context.getBeansOfType(ServletRegistrationBean.class)).hasSize(1); + this.contextLoader.load(context -> { + assertThat(context.getBeansOfType(ServletRegistrationBean.class)).hasSize(1); + }); } @Test public void customPathMustBeginWithASlash() { - this.thrown.expect(BeanCreationException.class); - this.thrown.expectMessage("Failed to bind properties under 'spring.webservices'"); - load(WebServicesAutoConfiguration.class, "spring.webservices.path=invalid"); - } - - @Test - public void customPathWithTrailingSlash() { - load(WebServicesAutoConfiguration.class, "spring.webservices.path=/valid/"); - ServletRegistrationBean servletRegistrationBean = this.context - .getBean(ServletRegistrationBean.class); - assertThat(servletRegistrationBean.getUrlMappings()).contains("/valid/*"); + this.contextLoader.env("spring.webservices.path=invalid") + .loadAndFail(BeanCreationException.class, (ex) -> { + System.out.println(ex.getMessage()); + assertThat(ex.getMessage()).contains( + "Failed to bind properties under 'spring.webservices'"); + }); } @Test public void customPath() { - load(WebServicesAutoConfiguration.class, "spring.webservices.path=/valid"); - assertThat(this.context.getBeansOfType(ServletRegistrationBean.class)).hasSize(1); - ServletRegistrationBean servletRegistrationBean = this.context - .getBean(ServletRegistrationBean.class); - assertThat(servletRegistrationBean.getUrlMappings()).contains("/valid/*"); + this.contextLoader.env("spring.webservices.path=/valid").load(context -> { + ServletRegistrationBean servletRegistrationBean = context + .getBean(ServletRegistrationBean.class); + assertThat(servletRegistrationBean.getUrlMappings()).contains("/valid/*"); + }); + } + + @Test + public void customPathWithTrailingSlash() { + this.contextLoader.env("spring.webservices.path=/valid/").load(context -> { + ServletRegistrationBean servletRegistrationBean = context + .getBean(ServletRegistrationBean.class); + assertThat(servletRegistrationBean.getUrlMappings()).contains("/valid/*"); + }); } @Test public void customLoadOnStartup() { - load(WebServicesAutoConfiguration.class, - "spring.webservices.servlet.load-on-startup=1"); - ServletRegistrationBean registrationBean = this.context - .getBean(ServletRegistrationBean.class); - assertThat(ReflectionTestUtils.getField(registrationBean, "loadOnStartup")) - .isEqualTo(1); + this.contextLoader.env("spring.webservices.servlet.load-on-startup=1") + .load(context -> { + ServletRegistrationBean registrationBean = context + .getBean(ServletRegistrationBean.class); + assertThat(ReflectionTestUtils.getField(registrationBean, + "loadOnStartup")).isEqualTo(1); + }); } @Test public void customInitParameters() { - load(WebServicesAutoConfiguration.class, - "spring.webservices.servlet.init.key1=value1", - "spring.webservices.servlet.init.key2=value2"); - ServletRegistrationBean registrationBean = this.context - .getBean(ServletRegistrationBean.class); - assertThat(registrationBean.getInitParameters()).containsEntry("key1", "value1"); - assertThat(registrationBean.getInitParameters()).containsEntry("key2", "value2"); - } - - private void load(Class config, String... environment) { - AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); - context.setServletContext(new MockServletContext()); - TestPropertyValues.of(environment).applyTo(context); - context.register(config); - context.refresh(); - this.context = context; + this.contextLoader.env("spring.webservices.servlet.init.key1=value1", + "spring.webservices.servlet.init.key2=value2").load(context -> { + ServletRegistrationBean registrationBean = context + .getBean(ServletRegistrationBean.class); + assertThat(registrationBean.getInitParameters()).containsEntry("key1", + "value1"); + assertThat(registrationBean.getInitParameters()).containsEntry("key2", + "value2"); + }); } } diff --git a/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/jdbc/TestDatabaseAutoConfigurationTests.java b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/jdbc/TestDatabaseAutoConfigurationTests.java index 7a419d0d57..dd0d174250 100644 --- a/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/jdbc/TestDatabaseAutoConfigurationTests.java +++ b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/jdbc/TestDatabaseAutoConfigurationTests.java @@ -18,12 +18,9 @@ package org.springframework.boot.test.autoconfigure.jdbc; import javax.sql.DataSource; -import org.junit.After; import org.junit.Test; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.boot.test.context.ContextLoader; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; @@ -36,52 +33,33 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link TestDatabaseAutoConfiguration}. * * @author Stephane Nicoll + * @author Andy Wilkinson */ public class TestDatabaseAutoConfigurationTests { - private ConfigurableApplicationContext context; - - @After - public void closeContext() { - if (this.context != null) { - this.context.close(); - } - } + private final ContextLoader contextLoader = new ContextLoader() + .autoConfig(TestDatabaseAutoConfiguration.class); @Test public void replaceWithNoDataSourceAvailable() { - load(null); - assertThat(this.context.getBeansOfType(DataSource.class)).isEmpty(); + this.contextLoader.load(context -> { + assertThat(context.getBeansOfType(DataSource.class)).isEmpty(); + }); } @Test public void replaceWithUniqueDatabase() { - load(ExistingDataSourceConfiguration.class); - DataSource datasource = this.context.getBean(DataSource.class); - JdbcTemplate jdbcTemplate = new JdbcTemplate(datasource); - jdbcTemplate.execute("create table example (id int, name varchar);"); - try (ConfigurableApplicationContext anotherContext = doLoad( - ExistingDataSourceConfiguration.class)) { - DataSource anotherDatasource = anotherContext.getBean(DataSource.class); - JdbcTemplate anotherJdbcTemplate = new JdbcTemplate(anotherDatasource); - anotherJdbcTemplate.execute("create table example (id int, name varchar);"); - } - } - - private void load(Class config, String... environment) { - this.context = doLoad(config, environment); - } - - private ConfigurableApplicationContext doLoad(Class config, - String... environment) { - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); - if (config != null) { - ctx.register(config); - } - ctx.register(TestDatabaseAutoConfiguration.class); - TestPropertyValues.of(environment).applyTo(ctx); - ctx.refresh(); - return ctx; + this.contextLoader.config(ExistingDataSourceConfiguration.class).load(context -> { + DataSource datasource = context.getBean(DataSource.class); + JdbcTemplate jdbcTemplate = new JdbcTemplate(datasource); + jdbcTemplate.execute("create table example (id int, name varchar);"); + this.contextLoader.load(anotherContext -> { + DataSource anotherDatasource = anotherContext.getBean(DataSource.class); + JdbcTemplate anotherJdbcTemplate = new JdbcTemplate(anotherDatasource); + anotherJdbcTemplate + .execute("create table example (id int, name varchar);"); + }); + }); } @Configuration diff --git a/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/orm/jpa/TestDatabaseAutoConfigurationNoEmbeddedTests.java b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/orm/jpa/TestDatabaseAutoConfigurationNoEmbeddedTests.java index 5db6b5ae46..5f5bdc7c84 100644 --- a/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/orm/jpa/TestDatabaseAutoConfigurationNoEmbeddedTests.java +++ b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/orm/jpa/TestDatabaseAutoConfigurationNoEmbeddedTests.java @@ -18,17 +18,14 @@ package org.springframework.boot.test.autoconfigure.orm.jpa; import javax.sql.DataSource; -import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.BeanCreationException; import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; -import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.boot.test.context.ContextLoader; import org.springframework.boot.testsupport.runner.classpath.ClassPathExclusions; import org.springframework.boot.testsupport.runner.classpath.ModifiedClassPathRunner; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -40,26 +37,19 @@ import static org.mockito.Mockito.mock; * available. * * @author Stephane Nicoll + * @author Andy Wilkinson */ @RunWith(ModifiedClassPathRunner.class) @ClassPathExclusions({ "h2-*.jar", "hsqldb-*.jar", "derby-*.jar" }) public class TestDatabaseAutoConfigurationNoEmbeddedTests { - private ConfigurableApplicationContext context; - - @After - public void closeContext() { - if (this.context != null) { - this.context.close(); - } - } + private final ContextLoader contextLoader = new ContextLoader() + .config(ExistingDataSourceConfiguration.class) + .autoConfig(TestDatabaseAutoConfiguration.class); @Test public void applyAnyReplace() { - try { - load(ExistingDataSourceConfiguration.class); - } - catch (BeanCreationException ex) { + this.contextLoader.loadAndFail(BeanCreationException.class, ex -> { String message = ex.getMessage(); assertThat(message).contains( "Failed to replace DataSource with an embedded database for tests."); @@ -68,30 +58,16 @@ public class TestDatabaseAutoConfigurationNoEmbeddedTests { + "classpath"); assertThat(message).contains( "or tune the replace attribute of @AutoconfigureTestDatabase."); - } + }); } @Test public void applyNoReplace() { - load(ExistingDataSourceConfiguration.class, "spring.test.database.replace=NONE"); - assertThat(this.context.getBeansOfType(DataSource.class)).hasSize(1); - assertThat(this.context.getBean(DataSource.class)) - .isSameAs(this.context.getBean("myCustomDataSource")); - } - - public void load(Class config, String... environment) { - this.context = doLoad(config, environment); - } - - public ConfigurableApplicationContext doLoad(Class config, String... environment) { - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); - if (config != null) { - ctx.register(config); - } - ctx.register(TestDatabaseAutoConfiguration.class); - TestPropertyValues.of(environment).applyTo(ctx); - ctx.refresh(); - return ctx; + this.contextLoader.env("spring.test.database.replace=NONE").load(context -> { + assertThat(context.getBeansOfType(DataSource.class)).hasSize(1); + assertThat(context.getBean(DataSource.class)) + .isSameAs(context.getBean("myCustomDataSource")); + }); } @Configuration diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/context/ContextLoader.java b/spring-boot-test/src/main/java/org/springframework/boot/test/context/ContextLoader.java index de3f49e034..623ca2978d 100644 --- a/spring-boot-test/src/main/java/org/springframework/boot/test/context/ContextLoader.java +++ b/spring-boot-test/src/main/java/org/springframework/boot/test/context/ContextLoader.java @@ -26,13 +26,19 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Consumer; +import java.util.function.Supplier; import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.boot.web.reactive.context.GenericReactiveWebApplicationContext; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.AnnotationConfigRegistry; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.mock.web.MockServletContext; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import static org.assertj.core.api.Assertions.assertThat; @@ -96,6 +102,8 @@ public class ContextLoader { private final LinkedList> autoConfigurations = new LinkedList<>(); + private Supplier contextSupplier = () -> new AnnotationConfigApplicationContext(); + private ClassLoader classLoader; /** @@ -182,6 +190,32 @@ public class ContextLoader { return this; } + /** + * Configures the loader to create an {@link ApplicationContext} suitable for use in a + * reactive web application. + * @return this instance + */ + public ContextLoader webReactive() { + this.contextSupplier = () -> { + return new GenericReactiveWebApplicationContext(); + }; + return this; + } + + /** + * Configures the loader to create an {@link ApplicationContext} suitable for use in a + * servlet web application. + * @return this instance + */ + public ContextLoader webServlet() { + this.contextSupplier = () -> { + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.setServletContext(new MockServletContext()); + return context; + }; + return this; + } + /** * Create and refresh a new {@link ApplicationContext} based on the current state of * this loader. The context is consumed by the specified {@link ContextConsumer} and @@ -239,25 +273,26 @@ public class ContextLoader { } private ConfigurableApplicationContext createApplicationContext() { - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ConfigurableApplicationContext context = ContextLoader.this.contextSupplier.get(); if (this.classLoader != null) { - ctx.setClassLoader(this.classLoader); + ((DefaultResourceLoader) context).setClassLoader(this.classLoader); } if (!ObjectUtils.isEmpty(this.env)) { TestPropertyValues.of(this.env.toArray(new String[this.env.size()])) - .applyTo(ctx); + .applyTo(context); } + AnnotationConfigRegistry registry = ((AnnotationConfigRegistry) context); if (!ObjectUtils.isEmpty(this.userConfigurations)) { - ctx.register(this.userConfigurations + registry.register(this.userConfigurations .toArray(new Class[this.userConfigurations.size()])); } if (!ObjectUtils.isEmpty(this.autoConfigurations)) { LinkedHashSet> linkedHashSet = new LinkedHashSet<>( this.autoConfigurations); - ctx.register( + registry.register( linkedHashSet.toArray(new Class[this.autoConfigurations.size()])); } - return ctx; + return context; } /**