Replace @Value property within @Configuration during Spring Boot test
Solution 1
You can use constructor injection in production cases, which allows it to set the configuration manually:
@Configuration
public class SomeConfiguration {
private final String someUsername;
private final String somePassword;
@Autowired
public SomeConfiguration(@Value("${some.username}") String someUsername,
@Value("${some.password}") String somePassword) {
this.someUsername = someUsername;
this.somePassword = somePassword;
}
...
)
}
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class SomeTest {
private SomeConfiguration config;
@Before
public init() {
config = new SomeConfiguration("foo", "bar");
}
}
Solution 2
You can override properties directly in the @SpringBootTest
annotation using the properties
parameter:
@SpringBootTest(properties = {"some.username=user", "some.password=pwd"},
webEnvironment = SpringBootTest.WebEnvironment.NONE)
Solution 3
You can use @TestPropertySource
@TestPropertySource(
properties = {
"some.username=validate",
"some.password=false"
}
)
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class ApplicationTest {
//...
}
Markus Ratzer
I'm a upper (I guess?) mid-range Java developer, mainly focused on back end technologies.
Updated on June 17, 2022Comments
-
Markus Ratzer almost 2 years
Scenario
I've got a Spring Boot application with a
@Configuration
annotated Spring configuration class which contains some@Value
annotated fields. For testing I want to replace these field values with custom test values.Unfortunately these test values cannot be overridden using a simple properties file, (String) constants or similar, instead I must use some custom written property resolving Java class (e.g.
TargetProperties.getProperty("some.username")
).The problem I have is that when I add a custom
PropertySource
to theConfigurableEnvironment
within my test configuration, it's already too late because thisPropertySource
will be added after the e.g.RestTemplate
has been created.Question
How can I override
@Value
annotated fields within a@Configuration
class with properties obtained programmatically via custom Java code before anything else gets initialized?Code
Production Configuration Class
@Configuration public class SomeConfiguration { @Value("${some.username}") private String someUsername; @Value("${some.password}") private String somePassword; @Bean public RestTemplate someRestTemplate() { RestTemplate restTemplate = new RestTemplate(); restTemplate.getInterceptors().add( new BasicAuthorizationInterceptor(someUsername, somePassword)); return restTemplate; } }
Test Configuration Class
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) public class SomeTest { @SpringBootConfiguration @Import({MySpringBootApp.class, SomeConfiguration.class}) static class TestConfiguration { @Autowired private ConfigurableEnvironment configurableEnvironment; // This doesn't work: @Bean @Lazy(false) // I also tried a @PostConstruct method public TargetPropertiesPropertySource targetPropertiesPropertySource() { TargetPropertiesPropertySource customPropertySource = new TargetPropertiesPropertySource(); configurableEnvironment.getPropertySources().addFirst(customPropertySource); return customPropertySource; } } }