What does the `properties = {}` attribute of `@SpringBootTest` do, and when would you use it?
answer
- key=value inlined into Environment
- same as @TestPropertySource(properties=...)
- overrides application.properties
- must be compile-time constant
- part of context-cache key
basics
~10 sIt sets configuration properties just for that test, in key=value form. Those values override the same keys from application.properties, so you can test the app under specific config without editing real files.
solid answer
~40 s`@SpringBootTest(properties = {"app.retries=3", "spring.jpa.show-sql=true"})` injects inlined properties into the test's `Environment` before the context starts. Each entry is a `key=value` string; they behave exactly like `@TestPropertySource(properties = ...)` and take precedence over `application.properties`, OS environment variables, and system properties. Use it to flip a feature flag, point at an in-memory value, disable a scheduler, or exercise a config branch for one test class — without touching real config files or profiles. Because the value is baked into the annotation it changes the context configuration, so tests with different `properties` get separate (non-cached) application contexts. For values only known at runtime (a container's random port) you need `@DynamicPropertySource` instead, since annotation attributes must be compile-time constants.
code
java · 15 lines@SpringBootTest(properties = {
"app.feature.new-checkout=true",
"spring.jpa.show-sql=false",
"spring.main.banner-mode=off"
})
class CheckoutServiceTest {
@Value("${app.feature.new-checkout}")
boolean newCheckoutEnabled;
@Test
void flagIsHonored() {
assertThat(newCheckoutEnabled).isTrue();
}
}go deeper
Know it sets key=value overrides scoped to the test and beats application.properties.
Explain it maps to inlined test properties and must be compile-time constants.
Discuss precedence vs other sources and the context-caching cost of differing arrays.
Frame it within the full property-source ordering and when to prefer profiles/@DynamicPropertySource for maintainability.
## What it is `@SpringBootTest` is the annotation that boots a full Spring `ApplicationContext` for an integration test. Its `properties` attribute accepts an array of `String` in `key=value` format: ```java @SpringBootTest(properties = { "app.feature.new-checkout=true", "spring.task.scheduling.pool.size=1" }) ``` Spring adds these as an **inlined test property source** to the `Environment` (the object that resolves `@Value`, `@ConfigurationProperties`, and `environment.getProperty(...)`). This is functionally identical to `@TestPropertySource(properties = {...})` — under the hood `@SpringBootTest#properties` is documented as an alias-like mechanism that contributes inlined properties. ## Why it exists You often need a bean to behave differently in a test: a shorter timeout, a disabled background job, a feature flag on. Editing `src/main/resources/application.properties` would change production behavior; a test-only profile file is heavier. `properties = {}` scopes the override to a single test class, right next to the code that relies on it. ## Precedence Inlined test properties sit near the top of Spring Boot's property-source ordering — above `application.properties`, OS environment variables, Java system properties, and command-line args. So `properties = {"server.port=0"}` reliably wins. (The only things above it are `@TestPropertySource` and `@DynamicPropertySource`.) ## Gotchas - **Values must be compile-time constants.** You cannot write `"db.url=" + container.getJdbcUrl()` because annotations require constant expressions. Runtime values need `@DynamicPropertySource`. - **Context caching.** Spring caches the `ApplicationContext` keyed by its configuration, and `properties` is part of that key. Two test classes with different `properties` arrays get two contexts — more startup cost. Reusing identical `properties` lets them share a cached context. - **Format.** Use `key=value`, one entry per array element. `key: value` (YAML style) does **not** work here; it's flat properties syntax. You *can* reference placeholders and use `spring.config.import` style keys, but each element is a single property. - **`spring.main.*` and framework keys work too**, e.g. `properties = {"spring.main.banner-mode=off"}`. ## When to use Static, known-at-compile-time overrides for one test class: feature flags, pool sizes, toggling `show-sql`, disabling a scheduler. For dynamic values use `@DynamicPropertySource`; for loading a whole file use `@TestPropertySource(locations=...)` or a test profile.
- Why can't you put `container.getJdbcUrl()` in `properties = {}`?Annotation attributes must be compile-time constant expressions, but a container URL is only known at runtime. Use `@DynamicPropertySource` with a static method and a `Supplier` for runtime values.
- Do two test classes with different `properties` share a cached context?No. The `properties` array is part of the context-cache key, so differing values force separate `ApplicationContext` instances, increasing startup cost.
saying these in an interview costs you the question
- Thinking `properties` edits or reads the real `application.properties` file
- Believing you can inline runtime values like a container URL
- Using YAML `key: value` syntax instead of flat `key=value`
- Assuming it never affects context caching