From 43015800951ed51573b29670aafd79bc470a9aee Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Mon, 6 Jul 2020 12:44:17 +0100 Subject: [PATCH] Improve testing of PropertyPlaceholderAutoConfiguration Since Spring Framework 4.3.0.RC2, a default embedded value resolver has been registered with the bean factory when one is not otherwise configured. This meant that placeholders in `@Value` would be resolved with or without PropertyPlaceholderAutoConfiguration defining a PropertySourcesPlaceholderConfigurer bean. However, placeholders in bean definitions would only be resolved if a PropertySourcesPlaceholderConfigurer was defined. This commit updates PropertyPlaceholderAutoConfigurationTests to align with this change in Framework. We now test that placeholders are resolved in `@Value` annotations with or without the auto-configuration and that placeholders in bean definitions are only resolved with the auto-configured. Closes gh-22230 --- ...ertyPlaceholderAutoConfigurationTests.java | 87 +++++++++++++------ 1 file changed, 61 insertions(+), 26 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/PropertyPlaceholderAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/PropertyPlaceholderAutoConfigurationTests.java index cb866b16f8..c0041e0d90 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/PropertyPlaceholderAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/PropertyPlaceholderAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,14 @@ package org.springframework.boot.autoconfigure.context; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; @@ -33,43 +35,75 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link PropertyPlaceholderAutoConfiguration}. * * @author Dave Syer + * @author Andy Wilkinson */ class PropertyPlaceholderAutoConfigurationTests { - private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); - @AfterEach - void close() { - if (this.context != null) { - this.context.close(); - } + @Test + void whenTheAutoConfigurationIsNotUsedThenBeanDefinitionPlaceholdersAreNotResolved() { + this.contextRunner.withPropertyValues("fruit:banana").withInitializer(this::definePlaceholderBean) + .run((context) -> assertThat(context.getBean(PlaceholderBean.class).fruit).isEqualTo("${fruit:apple}")); + } + + @Test + void whenTheAutoConfigurationIsUsedThenBeanDefinitionPlaceholdersAreResolved() { + this.contextRunner.withPropertyValues("fruit:banana").withInitializer(this::definePlaceholderBean) + .withConfiguration(AutoConfigurations.of(PropertyPlaceholderAutoConfiguration.class)) + .run((context) -> assertThat(context.getBean(PlaceholderBean.class).fruit).isEqualTo("banana")); } @Test - void propertyPlaceholders() { - this.context.register(PropertyPlaceholderAutoConfiguration.class, PlaceholderConfig.class); - TestPropertyValues.of("foo:two").applyTo(this.context); - this.context.refresh(); - assertThat(this.context.getBean(PlaceholderConfig.class).getFoo()).isEqualTo("two"); + void whenTheAutoConfigurationIsNotUsedThenValuePlaceholdersAreResolved() { + this.contextRunner.withPropertyValues("fruit:banana").withUserConfiguration(PlaceholderConfig.class) + .run((context) -> assertThat(context.getBean(PlaceholderConfig.class).fruit).isEqualTo("banana")); } @Test - void propertyPlaceholdersOverride() { - this.context.register(PropertyPlaceholderAutoConfiguration.class, PlaceholderConfig.class, - PlaceholdersOverride.class); - TestPropertyValues.of("foo:two").applyTo(this.context); - this.context.refresh(); - assertThat(this.context.getBean(PlaceholderConfig.class).getFoo()).isEqualTo("spam"); + void whenTheAutoConfigurationIsUsedThenValuePlaceholdersAreResolved() { + this.contextRunner.withPropertyValues("fruit:banana") + .withConfiguration(AutoConfigurations.of(PropertyPlaceholderAutoConfiguration.class)) + .withUserConfiguration(PlaceholderConfig.class) + .run((context) -> assertThat(context.getBean(PlaceholderConfig.class).fruit).isEqualTo("banana")); + } + + @Test + void whenThereIsAUserDefinedPropertySourcesPlaceholderConfigurerThenItIsUsedForBeanDefinitionPlaceholderResolution() { + this.contextRunner.withPropertyValues("fruit:banana").withInitializer(this::definePlaceholderBean) + .withConfiguration(AutoConfigurations.of(PropertyPlaceholderAutoConfiguration.class)) + .withUserConfiguration(PlaceholdersOverride.class) + .run((context) -> assertThat(context.getBean(PlaceholderBean.class).fruit).isEqualTo("orange")); + } + + @Test + void whenThereIsAUserDefinedPropertySourcesPlaceholderConfigurerThenItIsUsedForValuePlaceholderResolution() { + this.contextRunner.withPropertyValues("fruit:banana") + .withConfiguration(AutoConfigurations.of(PropertyPlaceholderAutoConfiguration.class)) + .withUserConfiguration(PlaceholderConfig.class, PlaceholdersOverride.class) + .run((context) -> assertThat(context.getBean(PlaceholderConfig.class).fruit).isEqualTo("orange")); + } + + private void definePlaceholderBean(ConfigurableApplicationContext context) { + ((BeanDefinitionRegistry) context.getBeanFactory()).registerBeanDefinition("placeholderBean", + BeanDefinitionBuilder.genericBeanDefinition(PlaceholderBean.class) + .addConstructorArgValue("${fruit:apple}").getBeanDefinition()); } @Configuration(proxyBeanMethods = false) static class PlaceholderConfig { - @Value("${foo:bar}") - private String foo; + @Value("${fruit:apple}") + private String fruit; + + } + + static class PlaceholderBean { + + private final String fruit; - String getFoo() { - return this.foo; + PlaceholderBean(String fruit) { + this.fruit = fruit; } } @@ -80,7 +114,8 @@ class PropertyPlaceholderAutoConfigurationTests { @Bean static PropertySourcesPlaceholderConfigurer morePlaceholders() { PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); - configurer.setProperties(StringUtils.splitArrayElementsIntoProperties(new String[] { "foo=spam" }, "=")); + configurer + .setProperties(StringUtils.splitArrayElementsIntoProperties(new String[] { "fruit=orange" }, "=")); configurer.setLocalOverride(true); configurer.setOrder(0); return configurer;