Similar to Springboot unit test set @Configuration Properties dynamically but the context is different.
In my case I have a TestContainer running a custom MySQL database that is prepopulated with a lot of data (not using the SQL batch loading approach because the data is an anonymized copy of production and doing it through SQLs makes the boot up time of the container 20 minutes vs 2 minutes).
So far my test looks like this
@RunWith(SpringRunner.class)
@SpringBootTest(
classes = {
Bootstrap.class
}
)
public class ITFakeDB {
@ClassRule
public static final GenericContainer DB = new GenericContainer("devdb")
.withExposedPorts(3306);
@Autowired
private DataSource dataSource;
@Autowired
private Users users;
@Test
public void testDatabaseIsUp() {
assertTrue(DB.getMappedPort(3306) != 0);
}
@Test
public void testUser() {
Optional<User> user = users.findByLoginName("mimi");
assertTrue(users.isPresent());
}
}
What I want to do is somehow set the spring.datasource.url
(or in my case datasources.schema1.url
because I did the routing datasource) to the one used by DB
You can manually override the property from within your Spring-boot test by using ContextConfiguration
and ApplicationContextInitializer
.
Override the property - define a static inner class:
static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
String url = "jdbc:mysql://" + DB.getContainerIpAddress() + ":" + DB.getMappedPort(3306) + "/my_db";
TestPropertyValues
.of("datasources.schema1.url=" + url)
.applyTo(configurableApplicationContext.getEnvironment());
}
}
Note: I have assumed that the url
is derived from the ip address, port and db name. You may change that part as needed but the core idea remains.
ApplicationContextInitializer
can be used for programmatically initializing a Spring context before context refresh. Now, wire up the context initializer class by annotating at test class level with ContextConfiguration
:
@ContextConfiguration(initializers = Initializer.class)
Docs:
ApplicationContextInitializer
ContextConfiguration
While the previous answer should work, Spring Framework 5.2.5 (that is included into Spring Boot 2.2.6) has introduced a new @DynamicPropertySource
annotation exactly for that case:
@DynamicPropertySource
static void initializeDatasource(DynamicPropertyRegistry registry) {
String ip = DB.getContainerIpAddress();
Integer port = DB.getMappedPort(3306);
String url = String.format("jdbc:mysql://%s:%d/my_db", ip, port);
registry.add("datasources.schema1.url", url);
}
See for details:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With