Spring-boot utilizes Spring profiles (http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html) which allow for instance to have separate config for different environments. One way I use this feature is to configure test database to be used by integration tests. I wonder however is it necessary to create my own profile 'test' and explicitly activate this profile in each test file? Right now I do it in the following way:
In every test file include:
@ActiveProfiles("test")
Is there a smarter / more concise way? For instance a default test profile?
Edit 1: This question pertains to Spring-Boot 1.4.1
This question is related to
java
spring
spring-boot
In my case I have different application.properties depending on the environment, something like:
application.properties (base file)
application-dev.properties
application-qa.properties
application-prod.properties
and application.properties contains a property spring.profiles.active to pick the proper file.
For my integration tests, I created a new application-test.properties
file inside test/resources
and with the @TestPropertySource({ "/application-test.properties" })
annotation this is the file who is in charge of picking the application.properties I want depending on my needs for those tests
If you use maven, you can add this in pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<argLine>-Dspring.profiles.active=test</argLine>
</configuration>
</plugin>
...
Then, maven should run your integration tests (*IT.java) using this arugument, and also IntelliJ will start with this profile activated - so you can then specify all properties inside
application-test.yml
and you should not need "-default" properties.
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).
Come 2021 and Spring Boot 2.4 the solution I have found is to have 3 properties files
src/main/resources/application.yml
- contains the application's default propssrc/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>
You can put your test specific properties into src/test/resources/config/application.properties
.
The properties defined in this file will override those defined in src/main/resources/application.properties
during testing.
For more information on why this works have a look at Spring Boots docs.
Another programatically way to do that:
import static org.springframework.core.env.AbstractEnvironment.DEFAULT_PROFILES_PROPERTY_NAME;
@BeforeClass
public static void setupTest() {
System.setProperty(DEFAULT_PROFILES_PROPERTY_NAME, "test");
}
It works great.
A delarative way to do that (In fact, a minor tweek to @Compito's original answer):
spring.profiles.active=test
in test/resources/application-default.properties
.test/resources/application-test.properties
for tests and override only the properties you need.To activate "test" profile write in your build.gradle:
test.doFirst {
systemProperty 'spring.profiles.active', 'test'
activeProfiles = 'test'
}
Add spring.profiles.active=tests
in your application.properties file, you can add multiple properties file in your spring boot application like application-stage.properties
, application-prod.properties
, etc. And you can specify in your application.properties file while file to refer by adding spring.profiles.active=stage
or spring.profiles.active=prod
you can also pass the profile at the time running the spring boot application by providing the command:
java -jar
-Dspring.profiles.active=local
build/libs/turtle-rnr-0.0.1-SNAPSHOT.jar
According to the profile name the properties file is picked up, in the above case passing profile local
consider the application-local.properties
file
If you simply want to set/use default profile at the time of making build through maven then, pass the argument
-Dspring.profiles.active=test
Just like
mvn clean install -Dspring.profiles.active=dev
Source: Stackoverflow.com