1. Overview

In this tutorial, we’ll look at various ways to override the properties in Spring’s tests.

Spring actually provides a number of solutions for this, so we have quite a bit to explore here.

2. Dependencies

Of course, in order to work with Spring tests, we need to add a test dependency:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

This dependency also includes JUnit 5 for us.

3. Setup

First, we’ll create a class in the application that will use our properties:

@Component
public class PropertySourceResolver {

    @Value("${example.firstProperty}") private String firstProperty;
    @Value("${example.secondProperty}") private String secondProperty;

    public String getFirstProperty() {
        return firstProperty;
    }

    public String getSecondProperty() {
        return secondProperty;
    }
}

Next, we’ll assign values to them. We can do this by creating the application.properties in the src/main/resources:

example.firstProperty=defaultFirst
example.secondProperty=defaultSecond

4. Overriding a Property File

Now we’ll override properties by putting the property file in the test resources. This file must be on the same classpath as the default one.

Additionally, it should contain all the property keys specified in the default file. Therefore, we’ll add the application.properties file into the src/test/resources:

example.firstProperty=file
example.secondProperty=file

Let’s also add the test that will make use of our solution:

@SpringBootTest
public class TestResourcePropertySourceResolverIntegrationTest {

    @Autowired private PropertySourceResolver propertySourceResolver;

    @Test
    public void shouldTestResourceFile_overridePropertyValues() {
        String firstProperty = propertySourceResolver.getFirstProperty();
        String secondProperty = propertySourceResolver.getSecondProperty();

        assertEquals("file", firstProperty);
        assertEquals("file", secondProperty);
    }
}

This method is very effective when we want to override multiple properties from the file.

And if we don’t put the example.secondProperty in the file, the application context won’t discover this property.

5. Spring Profiles

In this section, we’ll learn how to handle our issue by using Spring Profiles. Unlike the previous method, this one merges properties from the default file and the profiled file.

First, let’s create an applicationtest.properties file in the src/test/resources:

example.firstProperty=profile

Then we’ll create a test that will use the test profile:

@SpringBootTest
@ActiveProfiles("test")
public class ProfilePropertySourceResolverIntegrationTest {

    @Autowired private PropertySourceResolver propertySourceResolver;

    @Test
    public void shouldProfiledProperty_overridePropertyValues() {
        String firstProperty = propertySourceResolver.getFirstProperty();
        String secondProperty = propertySourceResolver.getSecondProperty();

        assertEquals("profile", firstProperty);
        assertEquals("defaultSecond", secondProperty);
    }
}

This approach allows us to use both default and test values. Therefore, this is a great method when we need to override multiple properties from a file, but we still want to use the default ones too.

We can learn more about Spring profiles in our Spring Profiles article.

6. @SpringBootTest

Another way to override the property value is to use the @SpringBootTest annotation:

@SpringBootTest(properties = { "example.firstProperty=annotation" })
public class SpringBootPropertySourceResolverIntegrationTest {

    @Autowired private PropertySourceResolver propertySourceResolver;

    @Test
    public void shouldSpringBootTestAnnotation_overridePropertyValues() {
        String firstProperty = propertySourceResolver.getFirstProperty();
        String secondProperty = propertySourceResolver.getSecondProperty();

        Assert.assertEquals("annotation", firstProperty);
        Assert.assertEquals("defaultSecond", secondProperty);
    }
}

As we can see, the example.firstProperty has been overridden, while the example.secondProperty hasn’t been. Therefore, this is a great solution when we need to override only specific properties for the test. This is the only method that requires the use of Spring Boot.

7. TestPropertySourceUtils

In this section, we’ll learn how to override properties by using the TestPropertySourceUtils class in the ApplicationContextInitializer.

The TestPropertySourceUtils comes with two methods that we can use to define a different property value.

Let’s create an initializer class that we’ll use in our test:

public class PropertyOverrideContextInitializer
  implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    static final String PROPERTY_FIRST_VALUE = "contextClass";

    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        TestPropertySourceUtils.addInlinedPropertiesToEnvironment(
          configurableApplicationContext, "example.firstProperty=" + PROPERTY_FIRST_VALUE);

        TestPropertySourceUtils.addPropertiesFilesToEnvironment(
          configurableApplicationContext, "context-override-application.properties");
    }
}

Next, we’ll add the context-override-application.properties file into src/test/resources:

example.secondProperty=contextFile

Finally, we should create a test class that will use our initializer:

@SpringBootTest
@ContextConfiguration(
  initializers = PropertyOverrideContextInitializer.class,
  classes = Application.class)
public class ContextPropertySourceResolverIntegrationTest {

    @Autowired private PropertySourceResolver propertySourceResolver;

    @Test
    public void shouldContext_overridePropertyValues() {
        final String firstProperty = propertySourceResolver.getFirstProperty();
        final String secondProperty = propertySourceResolver.getSecondProperty();

        assertEquals(PropertyOverrideContextInitializer.PROPERTY_FIRST_VALUE, firstProperty);
        assertEquals("contextFile", secondProperty);
    }
}

The example.firstProperty has been overridden from the inlined method.

The example.secondProperty has been overridden from the specific file in the second method. This approach allows us to define different property values when initializing the context.

8. Conclusion

In this article, we focused on the multiple ways we can override properties in our tests. We also discussed when to use each solution, or in some cases, when to mix them.

Of course, we have the @TestPropertySource annotation at our disposal as well.

As always, the code for the examples in this article is available over on GitHub.