skip to content

In @TestPropertySource, what's the difference between the properties/value attributes and the locations attribute, and which wins when both are used?

level: middleimportance: must knowfreq 60%

answer

  1. locations = files, properties = inline key=value
  2. inlined overrides locations
  3. single top-priority test property source
  4. default file <TestClass>.properties
  5. inheritLocations / inheritProperties default true

basics

~20 s

locations points to property files (e.g. "classpath:test.properties"); properties (or value) lists inlined key=value pairs directly in the annotation. When a key appears in both, the inlined properties win — they're applied last with higher precedence.

solid answer

~40 s

@TestPropertySource adds a property source to the test's Environment. Its locations attribute (alias value) lists resource paths to load, like classpath:/config/test.properties. Its properties attribute (alias inlinedProperties) is an array of "key=value" strings written directly in the annotation. Both feed the same test property source, but they have a defined precedence: inlined properties are added after and therefore override any same-named key from locations. Both, in turn, sit above the application's default property sources, so @TestPropertySource overrides application.properties. Use locations for a reusable file shared by many tests; use properties for a couple of one-off overrides local to a single test class. You can combine them — a shared file plus a class-specific tweak inlined on top.

code

java · 15 lines
java
@SpringBootTest
@TestPropertySource(
    locations = "classpath:/config/base-test.properties", // app.timeout=30
    properties = { "app.timeout=5", "app.retries=0" }      // overrides timeout -> 5
)
class PaymentServiceTest {

    @Value("${app.timeout}")
    int timeout;

    @Test
    void inlinedOverridesFile() {
        assertThat(timeout).isEqualTo(5); // inlined beats the file value 30
    }
}

go deeper

for a junior

Know locations = files, properties = inline pairs.

for a middle

Know inlined beats locations and both beat application.properties.

for a senior

Explain merge/inheritance semantics and the default <TestClass>.properties convention.

for a principal

Weigh cache-key impact and design shared vs. inline overrides for suite maintainability.

## Purpose `@TestPropertySource` (package `org.springframework.test.context`) is a class-level test annotation that **adds properties to the `Environment`** of a test's `ApplicationContext`. It exists to override or supply configuration values just for tests, without touching the real `application.properties`. ## Two ways to supply values 1. **`locations` (alias `value`)** — an array of resource paths to property files. Paths support Spring's resource prefixes: `classpath:/test.properties`, `file:/abs/path.properties`. If you omit `locations`, Spring looks for a **default** file named `<TestClass>.properties` in the same package (a `DefaultTestPropertySourceFactory` convention). 2. **`properties` (alias `inlinedProperties`)** — a `String[]` of `"key=value"` pairs written straight into the annotation, e.g. `properties = {"feature.x=true", "timeout=5"}`. Also accepts YAML-ish `key: value` form per entry. ```java @SpringBootTest @TestPropertySource( locations = "classpath:/config/test.properties", properties = { "app.timeout=5", "app.feature.x=true" } ) class ConfigTest { } ``` ## Precedence between the two Both contribute to a **single** test property source that is inserted with **highest precedence** in the `Environment`'s ordered list of property sources. Within that: the **inlined `properties` are applied last and therefore override** same-named keys coming from `locations`. So if `test.properties` sets `app.timeout=30` and the annotation inlines `app.timeout=5`, the effective value is `5`. ## Precedence versus the rest of the Environment The `@TestPropertySource` source outranks the application's own sources (`application.properties`, `application-<profile>.properties`, etc.). It does **not** automatically outrank things that are, by Spring's rules, even higher — notably **actual JVM system properties and OS environment variables** are still consulted with their normal (very high) precedence, but for ordinary application property files, `@TestPropertySource` wins. ## Merging and inheritance - By default a subclass **inherits** the parent's locations and inlined properties (`inheritLocations = true`, `inheritProperties = true`), merging them; the subclass's values win on conflict. Set either to `false` to replace instead of merge. - Multiple `locations` are loaded in listed order; later files override earlier ones for duplicate keys. ## When to use which - **`locations`**: a stable set of overrides shared across many test classes — keep it DRY in a file. - **`properties`**: one or two overrides specific to a single test class — inline them for locality and readability. - **Combine**: shared file + a per-class tweak on top. ## Gotchas - `@TestPropertySource` adds to the `Environment`; it does **not** activate profiles — that's `@ActiveProfiles`'s job. They're independent and often used together. - Each distinct set of inlined properties/locations changes the **context cache key**, so gratuitously varying them across test classes multiplies cached contexts. - It affects the `Environment` (`@Value`, `Environment.getProperty`, `@ConfigurationProperties` binding), not hard-coded literals.

  • If you list two files in locations with the same key, which value applies?
    The later file in the array wins — locations are loaded in order and duplicate keys are overridden by subsequent files.
  • What happens if you use @TestPropertySource with no locations and no properties?
    Spring falls back to a default file named <TestClassName>.properties in the same package; if it's missing, context loading fails.

saying these in an interview costs you the question

  • Claiming locations override inlined properties (it's the reverse)
  • Thinking @TestPropertySource activates profiles
  • Believing it only reads from a fixed application.properties

context