-
Notifications
You must be signed in to change notification settings - Fork 41.6k
Description
Problem statement
Hi Spring Team.
I'm evaluating Spring Boot 3.4.0-M3 and I ran into a regression in environment loading with tests using ApplicationContextRunner
to construct programmatic application contexts and assert on their behavior.
The behavior that appears to be lost is the Environment no longer resolves environment placeholders in the following example.
Autoconfiguration to conditionally create a different implementation of an interface
@Configuration
public class AppConfiguration {
@Bean
public Animal testAnimal(Environment environment) {
if (environment.getProperty("new.cat-mode.enabled", Boolean.class, false)) {
return new Cat();
}
return new Dog();
}
}
With an EnvironmentPostProcessor
to conditionally load a new property source
public class PropertyEnvironmentPostProcessor implements EnvironmentPostProcessor {
private static final String PROPERTY_SOURCE = "classpath:/custom-properties.properties";
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
if (environment.acceptsProfiles(Profiles.of("laptop"))) {
try {
environment.getPropertySources()
.addLast(new ResourcePropertySource("custom-prop", PROPERTY_SOURCE));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
Which loads a single property with a backport placeholder property
new.cat-mode.enabled=${old.cat-mode.enabled:true}
And finally the test to validate this behavior
public class AppConfigurationTest {
private final SpringApplication application = new SpringApplication();
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(AppConfiguration.class))
.withInitializer(
ac -> new PropertyEnvironmentPostProcessor().postProcessEnvironment(ac.getEnvironment(), application));
@Test
void testCatMode() {
contextRunner
.withSystemProperties("spring.profiles.active=laptop",
"spring.application.name=apptest")
.run(context -> {
assertThat(context).hasNotFailed();
assertThat(context).hasSingleBean(Cat.class);
});
}
@Test
void testDefaultMode() {
contextRunner
.run(context -> {
assertThat(context).hasNotFailed();
assertThat(context).hasSingleBean(Dog.class);
});
}
}
In Spring boot 3.3.x, this test passes. In 3.4.0-M3, it throws the following error with not being able to parse ${old.cat-mode.enabled:true}
as a boolean.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testAnimal' defined in com.example.demo.AppConfiguration: Failed to instantiate [com.example.demo.Animal]: Factory method 'testAnimal' threw exception with message: Failed to convert from type [java.lang.String] to type [java.lang.Boolean] for value [${old.cat-mode.enabled:true}]
Expectation
The expectation is there should be no changes in environment loading and placeholder resolution in this kind of test.
Proproducing this issue
I created the following Git repo that this test setup in 3.3.x and 3.4.0-M3.