Dynamic Property Registration
Spring Boot provides ways to register properties dynamically within the application context. This helps to:
Enhance Integration Testing: Particularly useful for integration tests utilizing Testcontainers, we can set properties based on container details dynamically.
Flexibility: Retrieve property values from external resources like databases or environment variables during runtime.
Implement Custom Logic: Design custom logic for determining property values, enabling complex test configurations or dynamic behavior adjustments.
Two key annotations for dynamic property registration are:
@DynamicPropertySource
: Used to register properties dynamically within the test class, particularly useful for integration tests. It is a method-level annotation.
Example:
Create Integration test file SampleIT.java
package org.example;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import java.util.function.Supplier;
@Slf4j
@SpringBootTest(classes = Application.class)
class SampleIT {
@Value("${service.client.url}")
private String testServiceUrlProperty;
@DynamicPropertySource
static void properties(DynamicPropertyRegistry registry) {
// Retrieve the property value dynamically (e.g., from a database or testcontainer)
String serverHost = "testcontainerHost";
int serverPort = 1080;
String path = "auth";
Supplier<Object> serviceUrl = () -> String.format("http://%s:%d/%s", serverHost, serverPort, path);
registry.add("service.client.url", serviceUrl);
}
@Test
void testDynamicProperties() {
log.info("testServiceUrlProperty: {}", testServiceUrlProperty);
Assertions.assertEquals("http://testcontainerHost:1080/auth", testServiceUrlProperty);
}
}

@TestPropertySource
: Not strictly for dynamic properties, but rather for overriding application properties specifically within the integration tests or for creating new static properties. It is a class-level annotation.
package org.example;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
@Slf4j
@SpringBootTest(classes = Application.class)
@TestPropertySource(properties = {
"spring.datasource.url=jdbc:h2:mem:testdb",
"spring.jpa.hibernate.ddl-auto=create-drop"
})
class SampleIT {
@Value("${spring.datasource.url}")
private String springDatasourceUrl;
@Value("${spring.jpa.hibernate.ddl-auto}")
private String springJpaProperty;
@Test
void testPropertySource() {
log.info("springDatasourceUrl: {}", springDatasourceUrl);
log.info("springJpaProperty: {}", springJpaProperty);
Assertions.assertEquals("jdbc:h2:mem:testdb", springDatasourceUrl);
Assertions.assertEquals("create-drop", springJpaProperty);
}
}

Last updated
Was this helpful?