Reputation: 1352
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 the ConfigurableEnvironment
within my test configuration, it's already too late because this PropertySource
will be added after the e.g. RestTemplate
has been created.
How can I override @Value
annotated fields within a @Configuration
class with properties obtained programmatically via custom Java code before anything else gets initialized?
@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;
}
}
@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;
}
}
}
Upvotes: 11
Views: 18110
Reputation: 9110
You can use @TestPropertySource
@TestPropertySource(
properties = {
"some.username=validate",
"some.password=false"
}
)
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class ApplicationTest {
//...
}
Upvotes: 12
Reputation: 17085
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)
Upvotes: 13
Reputation: 2542
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");
}
}
Upvotes: 6