From 29b1b38cc6e30121689cb82158ca9cb7fabe049b Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Thu, 28 Mar 2019 17:54:10 +0100 Subject: [PATCH 1/2] Migrate Thymeleaf tests to application runner --- ...ymeleafReactiveAutoConfigurationTests.java | 253 +++++++------ ...hymeleafServletAutoConfigurationTests.java | 357 +++++++++--------- 2 files changed, 308 insertions(+), 302 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafReactiveAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafReactiveAutoConfigurationTests.java index 85f4234a32..1818d05518 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafReactiveAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafReactiveAutoConfigurationTests.java @@ -22,7 +22,6 @@ import java.util.Locale; import nz.net.ultraq.thymeleaf.LayoutDialect; import nz.net.ultraq.thymeleaf.decorators.strategies.GroupingStrategy; -import org.junit.After; import org.junit.Rule; import org.junit.Test; import org.thymeleaf.TemplateEngine; @@ -36,14 +35,11 @@ import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver; import org.thymeleaf.spring5.view.reactive.ThymeleafReactiveViewResolver; import org.thymeleaf.templateresolver.ITemplateResolver; -import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; import org.springframework.boot.test.rule.OutputCapture; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.mock.http.server.reactive.MockServerHttpRequest; import org.springframework.mock.web.server.MockServerWebExchange; @@ -60,212 +56,215 @@ import static org.hamcrest.Matchers.not; * * @author Brian Clozel * @author Kazuki Shimizu + * @author Stephane Nicoll */ public class ThymeleafReactiveAutoConfigurationTests { @Rule public OutputCapture output = new OutputCapture(); - private AnnotationConfigReactiveWebApplicationContext context; - - @After - public void close() { - if (this.context != null) { - this.context.close(); - } - } + private ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(ThymeleafAutoConfiguration.class)); @Test public void createFromConfigClass() { - load(BaseConfiguration.class, "spring.thymeleaf.suffix:.html"); - TemplateEngine engine = this.context.getBean(TemplateEngine.class); - Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar")); - String result = engine.process("template", attrs); - assertThat(result).isEqualTo("bar"); + this.contextRunner.withPropertyValues("spring.thymeleaf.suffix:.html") + .run((context) -> { + TemplateEngine engine = context.getBean(TemplateEngine.class); + Context attrs = new Context(Locale.UK, + Collections.singletonMap("foo", "bar")); + String result = engine.process("template", attrs); + assertThat(result).isEqualTo("bar"); + }); } @Test public void overrideCharacterEncoding() { - load(BaseConfiguration.class, "spring.thymeleaf.encoding:UTF-16"); - ITemplateResolver resolver = this.context.getBean(ITemplateResolver.class); - assertThat(resolver instanceof SpringResourceTemplateResolver).isTrue(); - assertThat(((SpringResourceTemplateResolver) resolver).getCharacterEncoding()) - .isEqualTo("UTF-16"); - ThymeleafReactiveViewResolver views = this.context - .getBean(ThymeleafReactiveViewResolver.class); - assertThat(views.getDefaultCharset().name()).isEqualTo("UTF-16"); + this.contextRunner.withPropertyValues("spring.thymeleaf.encoding:UTF-16") + .run((context) -> { + ITemplateResolver resolver = context.getBean(ITemplateResolver.class); + assertThat(resolver) + .isInstanceOf(SpringResourceTemplateResolver.class); + assertThat(((SpringResourceTemplateResolver) resolver) + .getCharacterEncoding()).isEqualTo("UTF-16"); + ThymeleafReactiveViewResolver views = context + .getBean(ThymeleafReactiveViewResolver.class); + assertThat(views.getDefaultCharset().name()).isEqualTo("UTF-16"); + }); } @Test public void overrideMediaTypes() { - load(BaseConfiguration.class, - "spring.thymeleaf.reactive.media-types:text/html,text/plain"); - ThymeleafReactiveViewResolver views = this.context - .getBean(ThymeleafReactiveViewResolver.class); - assertThat(views.getSupportedMediaTypes()).contains(MediaType.TEXT_HTML, - MediaType.TEXT_PLAIN); + this.contextRunner + .withPropertyValues( + "spring.thymeleaf.reactive.media-types:text/html,text/plain") + .run((context) -> assertThat( + context.getBean(ThymeleafReactiveViewResolver.class) + .getSupportedMediaTypes()).contains(MediaType.TEXT_HTML, + MediaType.TEXT_PLAIN)); } @Test public void overrideTemplateResolverOrder() { - load(BaseConfiguration.class, "spring.thymeleaf.templateResolverOrder:25"); - ITemplateResolver resolver = this.context.getBean(ITemplateResolver.class); - assertThat(resolver.getOrder()).isEqualTo(Integer.valueOf(25)); + this.contextRunner.withPropertyValues("spring.thymeleaf.templateResolverOrder:25") + .run((context) -> assertThat( + context.getBean(ITemplateResolver.class).getOrder()) + .isEqualTo(Integer.valueOf(25))); } @Test public void overrideViewNames() { - load(BaseConfiguration.class, "spring.thymeleaf.viewNames:foo,bar"); - ThymeleafReactiveViewResolver views = this.context - .getBean(ThymeleafReactiveViewResolver.class); - assertThat(views.getViewNames()).isEqualTo(new String[] { "foo", "bar" }); + this.contextRunner.withPropertyValues("spring.thymeleaf.viewNames:foo,bar") + .run((context) -> assertThat(context + .getBean(ThymeleafReactiveViewResolver.class).getViewNames()) + .isEqualTo(new String[] { "foo", "bar" })); } @Test public void overrideMaxChunkSize() { - load(BaseConfiguration.class, "spring.thymeleaf.reactive.maxChunkSize:8KB"); - ThymeleafReactiveViewResolver views = this.context - .getBean(ThymeleafReactiveViewResolver.class); - assertThat(views.getResponseMaxChunkSizeBytes()).isEqualTo(Integer.valueOf(8192)); + this.contextRunner + .withPropertyValues("spring.thymeleaf.reactive.maxChunkSize:8KB") + .run((context) -> assertThat( + context.getBean(ThymeleafReactiveViewResolver.class) + .getResponseMaxChunkSizeBytes()) + .isEqualTo(Integer.valueOf(8192))); } @Test public void overrideFullModeViewNames() { - load(BaseConfiguration.class, - "spring.thymeleaf.reactive.fullModeViewNames:foo,bar"); - ThymeleafReactiveViewResolver views = this.context - .getBean(ThymeleafReactiveViewResolver.class); - assertThat(views.getFullModeViewNames()).isEqualTo(new String[] { "foo", "bar" }); + this.contextRunner + .withPropertyValues("spring.thymeleaf.reactive.fullModeViewNames:foo,bar") + .run((context) -> assertThat( + context.getBean(ThymeleafReactiveViewResolver.class) + .getFullModeViewNames()) + .isEqualTo(new String[] { "foo", "bar" })); } @Test public void overrideChunkedModeViewNames() { - load(BaseConfiguration.class, - "spring.thymeleaf.reactive.chunkedModeViewNames:foo,bar"); - ThymeleafReactiveViewResolver views = this.context - .getBean(ThymeleafReactiveViewResolver.class); - assertThat(views.getChunkedModeViewNames()) - .isEqualTo(new String[] { "foo", "bar" }); + this.contextRunner + .withPropertyValues( + "spring.thymeleaf.reactive.chunkedModeViewNames:foo,bar") + .run((context) -> assertThat( + context.getBean(ThymeleafReactiveViewResolver.class) + .getChunkedModeViewNames()) + .isEqualTo(new String[] { "foo", "bar" })); } @Test public void overrideEnableSpringElCompiler() { - load(BaseConfiguration.class, "spring.thymeleaf.enable-spring-el-compiler:true"); - assertThat(this.context.getBean(SpringWebFluxTemplateEngine.class) - .getEnableSpringELCompiler()).isTrue(); + this.contextRunner + .withPropertyValues("spring.thymeleaf.enable-spring-el-compiler:true") + .run((context) -> assertThat( + context.getBean(SpringWebFluxTemplateEngine.class) + .getEnableSpringELCompiler()).isTrue()); } @Test public void enableSpringElCompilerIsDisabledByDefault() { - load(BaseConfiguration.class); - assertThat(this.context.getBean(SpringWebFluxTemplateEngine.class) - .getEnableSpringELCompiler()).isFalse(); + this.contextRunner.run( + (context) -> assertThat(context.getBean(SpringWebFluxTemplateEngine.class) + .getEnableSpringELCompiler()).isFalse()); } @Test public void overrideRenderHiddenMarkersBeforeCheckboxes() { - load(BaseConfiguration.class, - "spring.thymeleaf.render-hidden-markers-before-checkboxes:true"); - assertThat(this.context.getBean(SpringWebFluxTemplateEngine.class) - .getRenderHiddenMarkersBeforeCheckboxes()).isTrue(); + this.contextRunner + .withPropertyValues( + "spring.thymeleaf.render-hidden-markers-before-checkboxes:true") + .run((context) -> assertThat( + context.getBean(SpringWebFluxTemplateEngine.class) + .getRenderHiddenMarkersBeforeCheckboxes()).isTrue()); } @Test public void enableRenderHiddenMarkersBeforeCheckboxesIsDisabledByDefault() { - load(BaseConfiguration.class); - assertThat(this.context.getBean(SpringWebFluxTemplateEngine.class) - .getRenderHiddenMarkersBeforeCheckboxes()).isFalse(); + this.contextRunner.run( + (context) -> assertThat(context.getBean(SpringWebFluxTemplateEngine.class) + .getRenderHiddenMarkersBeforeCheckboxes()).isFalse()); } @Test public void templateLocationDoesNotExist() { - load(BaseConfiguration.class, - "spring.thymeleaf.prefix:classpath:/no-such-directory/"); - this.output.expect(containsString("Cannot find template location")); + this.contextRunner + .withPropertyValues( + "spring.thymeleaf.prefix:classpath:/no-such-directory/") + .run((context) -> this.output + .expect(containsString("Cannot find template location"))); } @Test public void templateLocationEmpty() { new File("target/test-classes/templates/empty-directory").mkdir(); - load(BaseConfiguration.class, - "spring.thymeleaf.prefix:classpath:/templates/empty-directory/"); - this.output.expect(not(containsString("Cannot find template location"))); + this.contextRunner + .withPropertyValues( + "spring.thymeleaf.prefix:classpath:/templates/empty-directory/") + .run((context) -> this.output + .expect(not(containsString("Cannot find template location")))); } @Test public void useDataDialect() { - load(BaseConfiguration.class); - ISpringWebFluxTemplateEngine engine = this.context - .getBean(ISpringWebFluxTemplateEngine.class); - Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar")); - String result = engine.process("data-dialect", attrs); - assertThat(result).isEqualTo(""); + this.contextRunner.run((context) -> { + ISpringWebFluxTemplateEngine engine = context + .getBean(ISpringWebFluxTemplateEngine.class); + Context attrs = new Context(Locale.UK, + Collections.singletonMap("foo", "bar")); + String result = engine.process("data-dialect", attrs); + assertThat(result).isEqualTo(""); + }); } @Test public void useJava8TimeDialect() { - load(BaseConfiguration.class); - ISpringWebFluxTemplateEngine engine = this.context - .getBean(ISpringWebFluxTemplateEngine.class); - Context attrs = new Context(Locale.UK); - String result = engine.process("java8time-dialect", attrs); - assertThat(result).isEqualTo("2015-11-24"); + this.contextRunner.run((context) -> { + ISpringWebFluxTemplateEngine engine = context + .getBean(ISpringWebFluxTemplateEngine.class); + Context attrs = new Context(Locale.UK); + String result = engine.process("java8time-dialect", attrs); + assertThat(result).isEqualTo("2015-11-24"); + }); } @Test public void useSecurityDialect() { - load(BaseConfiguration.class); - ISpringWebFluxTemplateEngine engine = this.context - .getBean(ISpringWebFluxTemplateEngine.class); - MockServerWebExchange exchange = MockServerWebExchange - .from(MockServerHttpRequest.get("/test").build()); - exchange.getAttributes().put( - SpringSecurityContextUtils.SECURITY_CONTEXT_MODEL_ATTRIBUTE_NAME, - new SecurityContextImpl( - new TestingAuthenticationToken("alice", "admin"))); - IContext attrs = new SpringWebFluxContext(exchange); - String result = engine.process("security-dialect", attrs); - assertThat(result).isEqualTo( - "
alice
" + System.lineSeparator()); + this.contextRunner.run((context) -> { + ISpringWebFluxTemplateEngine engine = context + .getBean(ISpringWebFluxTemplateEngine.class); + MockServerWebExchange exchange = MockServerWebExchange + .from(MockServerHttpRequest.get("/test").build()); + exchange.getAttributes().put( + SpringSecurityContextUtils.SECURITY_CONTEXT_MODEL_ATTRIBUTE_NAME, + new SecurityContextImpl( + new TestingAuthenticationToken("alice", "admin"))); + IContext attrs = new SpringWebFluxContext(exchange); + String result = engine.process("security-dialect", attrs); + assertThat(result).isEqualTo("
alice
" + + System.lineSeparator()); + }); } @Test public void renderTemplate() { - load(BaseConfiguration.class); - ISpringWebFluxTemplateEngine engine = this.context - .getBean(ISpringWebFluxTemplateEngine.class); - Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar")); - String result = engine.process("home", attrs); - assertThat(result).isEqualTo("bar"); + this.contextRunner.run((context) -> { + ISpringWebFluxTemplateEngine engine = context + .getBean(ISpringWebFluxTemplateEngine.class); + Context attrs = new Context(Locale.UK, + Collections.singletonMap("foo", "bar")); + String result = engine.process("home", attrs); + assertThat(result).isEqualTo("bar"); + }); } @Test public void layoutDialectCanBeCustomized() { - load(LayoutDialectConfiguration.class); - LayoutDialect layoutDialect = this.context.getBean(LayoutDialect.class); - assertThat(ReflectionTestUtils.getField(layoutDialect, "sortingStrategy")) - .isInstanceOf(GroupingStrategy.class); - } - - private void load(Class config, String... envVariables) { - this.context = new AnnotationConfigReactiveWebApplicationContext(); - TestPropertyValues.of(envVariables).applyTo(this.context); - if (config != null) { - this.context.register(config); - } - this.context.register(config); - this.context.refresh(); - } - - @Configuration - @ImportAutoConfiguration({ ThymeleafAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class }) - protected static class BaseConfiguration { - + this.contextRunner.withUserConfiguration(LayoutDialectConfiguration.class) + .run((context) -> assertThat(ReflectionTestUtils.getField( + context.getBean(LayoutDialect.class), "sortingStrategy")) + .isInstanceOf(GroupingStrategy.class)); } @Configuration - @Import(BaseConfiguration.class) static class LayoutDialectConfiguration { @Bean diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafServletAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafServletAutoConfigurationTests.java index d77a4b9bfd..f4c649b95b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafServletAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafServletAutoConfigurationTests.java @@ -26,7 +26,6 @@ import javax.servlet.DispatcherType; import nz.net.ultraq.thymeleaf.LayoutDialect; import nz.net.ultraq.thymeleaf.decorators.strategies.GroupingStrategy; -import org.junit.After; import org.junit.Rule; import org.junit.Test; import org.thymeleaf.TemplateEngine; @@ -38,16 +37,14 @@ import org.thymeleaf.spring5.view.ThymeleafView; import org.thymeleaf.spring5.view.ThymeleafViewResolver; import org.thymeleaf.templateresolver.ITemplateResolver; -import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.test.rule.OutputCapture; -import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockServletContext; @@ -55,13 +52,13 @@ import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextImpl; import org.springframework.test.util.ReflectionTestUtils; -import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter; import org.springframework.web.servlet.support.RequestContext; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; /** * Tests for {@link ThymeleafAutoConfiguration} in Servlet-based applications. @@ -78,271 +75,284 @@ public class ThymeleafServletAutoConfigurationTests { @Rule public OutputCapture output = new OutputCapture(); - private AnnotationConfigWebApplicationContext context; - - @After - public void close() { - if (this.context != null) { - this.context.close(); - } - } + private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(ThymeleafAutoConfiguration.class)); @Test public void createFromConfigClass() { - load(BaseConfiguration.class, "spring.thymeleaf.mode:HTML", - "spring.thymeleaf.suffix:"); - TemplateEngine engine = this.context.getBean(TemplateEngine.class); - Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar")); - String result = engine.process("template.html", attrs); - assertThat(result).isEqualTo("bar"); + this.contextRunner.withPropertyValues("spring.thymeleaf.mode:HTML", + "spring.thymeleaf.suffix:").run((context) -> { + assertThat(context).hasSingleBean(TemplateEngine.class); + TemplateEngine engine = context.getBean(TemplateEngine.class); + Context attrs = new Context(Locale.UK, + Collections.singletonMap("foo", "bar")); + String result = engine.process("template.html", attrs); + assertThat(result).isEqualTo("bar"); + }); } @Test public void overrideCharacterEncoding() { - load(BaseConfiguration.class, "spring.thymeleaf.encoding:UTF-16"); - ITemplateResolver resolver = this.context.getBean(ITemplateResolver.class); - assertThat(resolver instanceof SpringResourceTemplateResolver).isTrue(); - assertThat(((SpringResourceTemplateResolver) resolver).getCharacterEncoding()) - .isEqualTo("UTF-16"); - ThymeleafViewResolver views = this.context.getBean(ThymeleafViewResolver.class); - assertThat(views.getCharacterEncoding()).isEqualTo("UTF-16"); - assertThat(views.getContentType()).isEqualTo("text/html;charset=UTF-16"); + this.contextRunner.withPropertyValues("spring.thymeleaf.encoding:UTF-16") + .run((context) -> { + ITemplateResolver resolver = context.getBean(ITemplateResolver.class); + assertThat(resolver) + .isInstanceOf(SpringResourceTemplateResolver.class); + assertThat(((SpringResourceTemplateResolver) resolver) + .getCharacterEncoding()).isEqualTo("UTF-16"); + ThymeleafViewResolver views = context + .getBean(ThymeleafViewResolver.class); + assertThat(views.getCharacterEncoding()).isEqualTo("UTF-16"); + assertThat(views.getContentType()) + .isEqualTo("text/html;charset=UTF-16"); + }); } @Test public void overrideDisableProducePartialOutputWhileProcessing() { - load(BaseConfiguration.class, - "spring.thymeleaf.servlet.produce-partial-output-while-processing:false"); - assertThat(this.context.getBean(ThymeleafViewResolver.class) - .getProducePartialOutputWhileProcessing()).isFalse(); + this.contextRunner.withPropertyValues( + "spring.thymeleaf.servlet.produce-partial-output-while-processing:false") + .run((context) -> assertThat(context.getBean(ThymeleafViewResolver.class) + .getProducePartialOutputWhileProcessing()).isFalse()); } @Test public void disableProducePartialOutputWhileProcessingIsEnabledByDefault() { - load(BaseConfiguration.class); - assertThat(this.context.getBean(ThymeleafViewResolver.class) - .getProducePartialOutputWhileProcessing()).isTrue(); + this.contextRunner + .run((context) -> assertThat(context.getBean(ThymeleafViewResolver.class) + .getProducePartialOutputWhileProcessing()).isTrue()); } @Test public void overrideTemplateResolverOrder() { - load(BaseConfiguration.class, "spring.thymeleaf.templateResolverOrder:25"); - ITemplateResolver resolver = this.context.getBean(ITemplateResolver.class); - assertThat(resolver.getOrder()).isEqualTo(Integer.valueOf(25)); + this.contextRunner.withPropertyValues("spring.thymeleaf.templateResolverOrder:25") + .run((context) -> assertThat( + context.getBean(ITemplateResolver.class).getOrder()) + .isEqualTo(Integer.valueOf(25))); } @Test public void overrideViewNames() { - load(BaseConfiguration.class, "spring.thymeleaf.viewNames:foo,bar"); - ThymeleafViewResolver views = this.context.getBean(ThymeleafViewResolver.class); - assertThat(views.getViewNames()).isEqualTo(new String[] { "foo", "bar" }); + this.contextRunner.withPropertyValues("spring.thymeleaf.viewNames:foo,bar") + .run((context) -> assertThat( + context.getBean(ThymeleafViewResolver.class).getViewNames()) + .isEqualTo(new String[] { "foo", "bar" })); } @Test public void overrideEnableSpringElCompiler() { - load(BaseConfiguration.class, "spring.thymeleaf.enable-spring-el-compiler:true"); - assertThat(this.context.getBean(SpringTemplateEngine.class) - .getEnableSpringELCompiler()).isTrue(); + this.contextRunner + .withPropertyValues("spring.thymeleaf.enable-spring-el-compiler:true") + .run((context) -> assertThat(context.getBean(SpringTemplateEngine.class) + .getEnableSpringELCompiler()).isTrue()); } @Test public void enableSpringElCompilerIsDisabledByDefault() { - load(BaseConfiguration.class); - assertThat(this.context.getBean(SpringTemplateEngine.class) - .getEnableSpringELCompiler()).isFalse(); + this.contextRunner.run((context) -> assertThat( + context.getBean(SpringTemplateEngine.class).getEnableSpringELCompiler()) + .isFalse()); } @Test public void overrideRenderHiddenMarkersBeforeCheckboxes() { - load(BaseConfiguration.class, - "spring.thymeleaf.render-hidden-markers-before-checkboxes:true"); - assertThat(this.context.getBean(SpringTemplateEngine.class) - .getRenderHiddenMarkersBeforeCheckboxes()).isTrue(); + this.contextRunner + .withPropertyValues( + "spring.thymeleaf.render-hidden-markers-before-checkboxes:true") + .run((context) -> assertThat(context.getBean(SpringTemplateEngine.class) + .getRenderHiddenMarkersBeforeCheckboxes()).isTrue()); } @Test public void enableRenderHiddenMarkersBeforeCheckboxesIsDisabledByDefault() { - load(BaseConfiguration.class); - assertThat(this.context.getBean(SpringTemplateEngine.class) - .getRenderHiddenMarkersBeforeCheckboxes()).isFalse(); + this.contextRunner + .run((context) -> assertThat(context.getBean(SpringTemplateEngine.class) + .getRenderHiddenMarkersBeforeCheckboxes()).isFalse()); } @Test public void templateLocationDoesNotExist() { - load(BaseConfiguration.class, - "spring.thymeleaf.prefix:classpath:/no-such-directory/"); - this.output.expect(containsString("Cannot find template location")); + this.contextRunner + .withPropertyValues( + "spring.thymeleaf.prefix:classpath:/no-such-directory/") + .run((context) -> this.output + .expect(containsString("Cannot find template location"))); } @Test public void templateLocationEmpty() { new File("target/test-classes/templates/empty-directory").mkdir(); - load(BaseConfiguration.class, - "spring.thymeleaf.prefix:classpath:/templates/empty-directory/"); + this.contextRunner + .withPropertyValues( + "spring.thymeleaf.prefix:classpath:/templates/empty-directory/") + .run((context) -> this.output + .expect(not(containsString("Cannot find template location")))); } @Test - public void createLayoutFromConfigClass() throws Exception { - AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); - context.register(ThymeleafAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class); - MockServletContext servletContext = new MockServletContext(); - context.setServletContext(servletContext); - context.refresh(); - ThymeleafView view = (ThymeleafView) context.getBean(ThymeleafViewResolver.class) - .resolveViewName("view", Locale.UK); - MockHttpServletResponse response = new MockHttpServletResponse(); - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setAttribute(RequestContext.WEB_APPLICATION_CONTEXT_ATTRIBUTE, context); - view.render(Collections.singletonMap("foo", "bar"), request, response); - String result = response.getContentAsString(); - assertThat(result).contains("Content"); - assertThat(result).contains("bar"); - context.close(); + public void createLayoutFromConfigClass() { + this.contextRunner.run((context) -> { + ThymeleafView view = (ThymeleafView) context + .getBean(ThymeleafViewResolver.class) + .resolveViewName("view", Locale.UK); + MockHttpServletResponse response = new MockHttpServletResponse(); + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setAttribute(RequestContext.WEB_APPLICATION_CONTEXT_ATTRIBUTE, + context); + view.render(Collections.singletonMap("foo", "bar"), request, response); + String result = response.getContentAsString(); + assertThat(result).contains("Content"); + assertThat(result).contains("bar"); + context.close(); + }); } @Test public void useDataDialect() { - load(BaseConfiguration.class); - TemplateEngine engine = this.context.getBean(TemplateEngine.class); - Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar")); - String result = engine.process("data-dialect", attrs); - assertThat(result).isEqualTo(""); + this.contextRunner.run((context) -> { + TemplateEngine engine = context.getBean(TemplateEngine.class); + Context attrs = new Context(Locale.UK, + Collections.singletonMap("foo", "bar")); + String result = engine.process("data-dialect", attrs); + assertThat(result).isEqualTo(""); + }); } @Test public void useJava8TimeDialect() { - load(BaseConfiguration.class); - TemplateEngine engine = this.context.getBean(TemplateEngine.class); - Context attrs = new Context(Locale.UK); - String result = engine.process("java8time-dialect", attrs); - assertThat(result).isEqualTo("2015-11-24"); + this.contextRunner.run((context) -> { + TemplateEngine engine = context.getBean(TemplateEngine.class); + Context attrs = new Context(Locale.UK); + String result = engine.process("java8time-dialect", attrs); + assertThat(result).isEqualTo("2015-11-24"); + }); } @Test public void useSecurityDialect() { - load(BaseConfiguration.class); - TemplateEngine engine = this.context.getBean(TemplateEngine.class); - WebContext attrs = new WebContext(new MockHttpServletRequest(), - new MockHttpServletResponse(), new MockServletContext()); - try { - SecurityContextHolder.setContext(new SecurityContextImpl( - new TestingAuthenticationToken("alice", "admin"))); - String result = engine.process("security-dialect", attrs); - assertThat(result).isEqualTo("
alice
" - + System.lineSeparator()); - } - finally { - SecurityContextHolder.clearContext(); - } + this.contextRunner.run((context) -> { + TemplateEngine engine = context.getBean(TemplateEngine.class); + WebContext attrs = new WebContext(new MockHttpServletRequest(), + new MockHttpServletResponse(), new MockServletContext()); + try { + SecurityContextHolder.setContext(new SecurityContextImpl( + new TestingAuthenticationToken("alice", "admin"))); + String result = engine.process("security-dialect", attrs); + assertThat(result).isEqualTo("
alice
" + + System.lineSeparator()); + } + finally { + SecurityContextHolder.clearContext(); + } + }); } @Test public void renderTemplate() { - load(BaseConfiguration.class); - TemplateEngine engine = this.context.getBean(TemplateEngine.class); - Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar")); - String result = engine.process("home", attrs); - assertThat(result).isEqualTo("bar"); + this.contextRunner.run((context) -> { + TemplateEngine engine = context.getBean(TemplateEngine.class); + Context attrs = new Context(Locale.UK, + Collections.singletonMap("foo", "bar")); + String result = engine.process("home", attrs); + assertThat(result).isEqualTo("bar"); + }); } @Test public void renderNonWebAppTemplate() { - try (AnnotationConfigApplicationContext customContext = new AnnotationConfigApplicationContext( - ThymeleafAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class)) { - assertThat(customContext.getBeanNamesForType(ViewResolver.class).length) - .isEqualTo(0); - TemplateEngine engine = customContext.getBean(TemplateEngine.class); - Context attrs = new Context(Locale.UK, - Collections.singletonMap("greeting", "Hello World")); - String result = engine.process("message", attrs); - assertThat(result).contains("Hello World"); - } + new ApplicationContextRunner() + .withConfiguration( + AutoConfigurations.of(ThymeleafAutoConfiguration.class)) + .run((context) -> { + assertThat(context).doesNotHaveBean(ViewResolver.class); + TemplateEngine engine = context.getBean(TemplateEngine.class); + Context attrs = new Context(Locale.UK, + Collections.singletonMap("greeting", "Hello World")); + String result = engine.process("message", attrs); + assertThat(result).contains("Hello World"); + }); } @Test public void registerResourceHandlingFilterDisabledByDefault() { - load(BaseConfiguration.class); - assertThat(this.context.getBeansOfType(FilterRegistrationBean.class)).isEmpty(); + this.contextRunner.run((context) -> assertThat(context) + .doesNotHaveBean(FilterRegistrationBean.class)); } @Test public void registerResourceHandlingFilterOnlyIfResourceChainIsEnabled() { - load(BaseConfiguration.class, "spring.resources.chain.enabled:true"); - FilterRegistrationBean registration = this.context - .getBean(FilterRegistrationBean.class); - assertThat(registration.getFilter()) - .isInstanceOf(ResourceUrlEncodingFilter.class); - assertThat(registration).hasFieldOrPropertyWithValue("dispatcherTypes", - EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR)); + this.contextRunner.withPropertyValues("spring.resources.chain.enabled:true") + .run((context) -> { + FilterRegistrationBean registration = context + .getBean(FilterRegistrationBean.class); + assertThat(registration.getFilter()) + .isInstanceOf(ResourceUrlEncodingFilter.class); + assertThat(registration).hasFieldOrPropertyWithValue( + "dispatcherTypes", + EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR)); + }); } @Test @SuppressWarnings("rawtypes") public void registerResourceHandlingFilterWithOtherRegistrationBean() { // gh-14897 - load(FilterRegistrationOtherConfiguration.class, - "spring.resources.chain.enabled:true"); - Map beans = this.context - .getBeansOfType(FilterRegistrationBean.class); - assertThat(beans).hasSize(2); - FilterRegistrationBean registration = beans.values().stream() - .filter((r) -> r.getFilter() instanceof ResourceUrlEncodingFilter) - .findFirst().get(); - assertThat(registration).hasFieldOrPropertyWithValue("dispatcherTypes", - EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR)); + this.contextRunner + .withUserConfiguration(FilterRegistrationOtherConfiguration.class) + .withPropertyValues("spring.resources.chain.enabled:true") + .run((context) -> { + Map beans = context + .getBeansOfType(FilterRegistrationBean.class); + assertThat(beans).hasSize(2); + FilterRegistrationBean registration = beans.values().stream().filter( + (r) -> r.getFilter() instanceof ResourceUrlEncodingFilter) + .findFirst().get(); + assertThat(registration).hasFieldOrPropertyWithValue( + "dispatcherTypes", + EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR)); + }); } @Test @SuppressWarnings("rawtypes") public void registerResourceHandlingFilterWithResourceRegistrationBean() { // gh-14926 - load(FilterRegistrationResourceConfiguration.class, - "spring.resources.chain.enabled:true"); - Map beans = this.context - .getBeansOfType(FilterRegistrationBean.class); - assertThat(beans).hasSize(1); - FilterRegistrationBean registration = beans.values().stream() - .filter((r) -> r.getFilter() instanceof ResourceUrlEncodingFilter) - .findFirst().get(); - assertThat(registration).hasFieldOrPropertyWithValue("dispatcherTypes", - EnumSet.of(DispatcherType.INCLUDE)); + this.contextRunner + .withUserConfiguration(FilterRegistrationResourceConfiguration.class) + .withPropertyValues("spring.resources.chain.enabled:true") + .run((context) -> { + Map beans = context + .getBeansOfType(FilterRegistrationBean.class); + assertThat(beans).hasSize(1); + FilterRegistrationBean registration = beans.values().stream().filter( + (r) -> r.getFilter() instanceof ResourceUrlEncodingFilter) + .findFirst().get(); + assertThat(registration).hasFieldOrPropertyWithValue( + "dispatcherTypes", EnumSet.of(DispatcherType.INCLUDE)); + }); } @Test public void layoutDialectCanBeCustomized() { - load(LayoutDialectConfiguration.class); - LayoutDialect layoutDialect = this.context.getBean(LayoutDialect.class); - assertThat(ReflectionTestUtils.getField(layoutDialect, "sortingStrategy")) - .isInstanceOf(GroupingStrategy.class); + this.contextRunner.withUserConfiguration(LayoutDialectConfiguration.class) + .run((context) -> assertThat(ReflectionTestUtils.getField( + context.getBean(LayoutDialect.class), "sortingStrategy")) + .isInstanceOf(GroupingStrategy.class)); } @Test public void cachingCanBeDisabled() { - load(BaseConfiguration.class, "spring.thymeleaf.cache:false"); - assertThat(this.context.getBean(ThymeleafViewResolver.class).isCache()).isFalse(); - SpringResourceTemplateResolver templateResolver = this.context - .getBean(SpringResourceTemplateResolver.class); - assertThat(templateResolver.isCacheable()).isFalse(); - } - - private void load(Class config, String... envVariables) { - this.context = new AnnotationConfigWebApplicationContext(); - TestPropertyValues.of(envVariables).applyTo(this.context); - this.context.register(config); - this.context.refresh(); - } - - @Configuration - @ImportAutoConfiguration({ ThymeleafAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class }) - static class BaseConfiguration { - + this.contextRunner.withPropertyValues("spring.thymeleaf.cache:false") + .run((context) -> { + assertThat(context.getBean(ThymeleafViewResolver.class).isCache()) + .isFalse(); + SpringResourceTemplateResolver templateResolver = context + .getBean(SpringResourceTemplateResolver.class); + assertThat(templateResolver.isCacheable()).isFalse(); + }); } @Configuration - @Import(BaseConfiguration.class) static class LayoutDialectConfiguration { @Bean @@ -353,12 +363,11 @@ public class ThymeleafServletAutoConfigurationTests { } @Configuration - @Import(BaseConfiguration.class) static class FilterRegistrationResourceConfiguration { @Bean public FilterRegistrationBean filterRegistration() { - FilterRegistrationBean bean = new FilterRegistrationBean( + FilterRegistrationBean bean = new FilterRegistrationBean<>( new ResourceUrlEncodingFilter()); bean.setDispatcherTypes(EnumSet.of(DispatcherType.INCLUDE)); return bean; @@ -367,13 +376,11 @@ public class ThymeleafServletAutoConfigurationTests { } @Configuration - @Import(BaseConfiguration.class) static class FilterRegistrationOtherConfiguration { @Bean public FilterRegistrationBean filterRegistration() { - return new FilterRegistrationBean( - new OrderedCharacterEncodingFilter()); + return new FilterRegistrationBean<>(new OrderedCharacterEncodingFilter()); } } From 6c3d64a2eb1e45c693ec859cc1132804a988e9a9 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Thu, 28 Mar 2019 17:59:22 +0100 Subject: [PATCH 2/2] Test Thymeleaf auto-configuration backs off without spring integration See gh-16341 --- .../ThymeleafServletAutoConfigurationTests.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafServletAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafServletAutoConfigurationTests.java index f4c649b95b..ae056e4d9f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafServletAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafServletAutoConfigurationTests.java @@ -38,6 +38,7 @@ import org.thymeleaf.spring5.view.ThymeleafViewResolver; import org.thymeleaf.templateresolver.ITemplateResolver; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.test.rule.OutputCapture; @@ -78,6 +79,14 @@ public class ThymeleafServletAutoConfigurationTests { private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() .withConfiguration(AutoConfigurations.of(ThymeleafAutoConfiguration.class)); + @Test + public void autoConfigurationBackOffWithoutThymeleafSpring() { + this.contextRunner + .withClassLoader(new FilteredClassLoader("org.thymeleaf.spring5")) + .run((context) -> assertThat(context) + .doesNotHaveBean(TemplateEngine.class)); + } + @Test public void createFromConfigClass() { this.contextRunner.withPropertyValues("spring.thymeleaf.mode:HTML",