Spring-boot default profile for integration tests

There are two approaches.

Load from config/

(2022 update, tested against Spring Boot 2.6)

Along with the approach below, you can also add config to src/test/resources/config/application.yml

src/
├── main/
│   ├── java/
│   │   └── ...
│   └── resources/
│       └── application.yml <- default properties, always loaded
└── test/
    ├── java/
    │   └── ...
    └── resources/
        └── config/
            └── application.yml <- test properties, will override the defaults

https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config.files

Spring Boot will automatically find and load application.properties and application.yaml files from the following locations when your application starts:

  1. From the classpath
    1. The classpath root
    2. The classpath /config package
  2. From the current directory
    1. The current directory
    2. The /config subdirectory in the current directory
    3. Immediate child directories of the /config subdirectory

The list is ordered by precedence (with values from lower items overriding earlier ones). Documents from the loaded files are added as PropertySources to the Spring Environment.

Manual import using spring.config.import

(original answer from 2021, tested against Spring Boot 2.4)

One solution is to have 3 properties files and to import

  • src/main/resources/application.yml - contains the application's default props
  • src/test/resources/application.yml - sets the profile to 'test', and imports properties from 'main'
  • src/test/resources/application-test.yml - contains test-specific profiles, which will override 'main'

Here is the content of src/test/resources/application.yml:

# for testing, set default profile to 'test'
spring.profiles.active: "test"
# and import the 'main' properties
spring.config.import: file:src/main/resources/application.yml

For example, if src/main/resources/application.yml has the content

ip-address: "10.7.0.1"
username: admin

and src/test/resources/application-test.yml has

ip-address: "999.999.999.999"
run-integration-test: true

Then (assuming there are no other profiles)...

when running tests,

profiles=test
--
ip-address=999.999.999.999
username=admin
run-integration-test=true

and when running the application normally

profiles=none
--
ip-address=10.7.0.1
username=admin
run-integration-test <undefined>

Note: if src/main/resources/application.yml contains spring.profiles.active: "dev", then this won't be overwritten by src/test/resources/application-test.yml


As far as I know there is nothing directly addressing your request - but I can suggest a proposal that could help:

You could use your own test annotation that is a meta annotation comprising @SpringBootTest and @ActiveProfiles("test"). So you still need the dedicated profile but avoid scattering the profile definition across all your test.

This annotation will default to the profile test and you can override the profile using the meta annotation.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@SpringBootTest
@ActiveProfiles
public @interface MyApplicationTest {
  @AliasFor(annotation = ActiveProfiles.class, attribute = "profiles") String[] activeProfiles() default {"test"};
}

You could put an application.properties file in your test/resources folder. There you set

spring.profiles.active=test

This is kind of a default test profile while running tests.


Another way to do this is to define a base (abstract) test class that your actual test classes will extend :

@RunWith(SpringRunner.class)
@SpringBootTest()
@ActiveProfiles("staging")
public abstract class BaseIntegrationTest {
}

Concrete test :

public class SampleSearchServiceTest extends BaseIntegrationTest{

    @Inject
    private SampleSearchService service;

    @Test
    public void shouldInjectService(){
        assertThat(this.service).isNotNull();
    }
} 

This allows you to extract more than just the @ActiveProfiles annotation. You could also imagine more specialised base classes for different kinds of integration tests, e.g. data access layer vs service layer, or for functional specialties (common @Before or @After methods etc).