How do you use test-specific configuration (@TestPropertySource, application-test.yml, test profiles)?
Quick Answer
Test-specific configuration lets you override properties (a test database URL, a disabled external integration, a faster-but-less-secure encoder) only for the test run, without touching the application's real configuration files. Common approaches: an application-test.yml/properties file activated via a dedicated 'test' Spring profile (@ActiveProfiles("test")), or @TestPropertySource to set/override specific properties directly on a test class, both of which layer on top of (and can override) the application's normal configuration precedence.
Detailed Answer
Tests frequently need different configuration than the real application — a test-only database URL, a disabled or stubbed-out external integration, relaxed security settings for convenience, or faster (if less secure) settings that would be inappropriate in production but are fine for a test run.
1. A dedicated test profile, with its own properties file:
src/test/resources/application-test.yml
spring:
datasource:
url: jdbc:h2:mem:testdb
logging:
level:
org.springframework: WARN
Activated on the test class:
@SpringBootTest
@ActiveProfiles("test") // loads application-test.yml on top of the base application.yml
class OrderServiceIntegrationTest { ... }
2. @TestPropertySource — set or override specific properties directly on the test class, without a separate profile-specific file:
@SpringBootTest
@TestPropertySource(properties = {
"app.feature.new-checkout-flow.enabled=false",
"spring.datasource.url=jdbc:h2:mem:testdb"
})
class CheckoutServiceTest { ... }
Can also point at a specific properties file: @TestPropertySource(locations = "classpath:test-specific.properties").
Both approaches layer on top of Spring Boot's normal configuration precedence — a test-specific property (whether from a profile-specific file or @TestPropertySource) overrides the base application.yml's value for that property, exactly as an active-profile file would in a non-test context, letting the same overall configuration-resolution model apply consistently to both production and test scenarios.
Practical guidance on choosing between them:
- Use a dedicated
application-test.yml+@ActiveProfiles("test")for a broader, reusable set of test-environment defaults shared across many test classes (e.g., "tests always use an in-memory database and disabled external calls"). - Use
@TestPropertySourcefor a small number of property overrides specific to one particular test class's needs, where creating an entire separate profile file would be overkill.
Both are commonly combined with @DynamicPropertySource (seen in the Testcontainers example) when a property's value isn't known statically ahead of time — e.g., a Testcontainers-assigned random port — since @TestPropertySource/profile files can only hold static values known at compile/config time.