Spring TestPropertySource Example
@TestPropertySource in Spring is an annotation used in testing to specify a custom property source for configuration properties. It allows developers to override or provide specific properties for test environments, ensuring isolated and controlled testing conditions. Let us delve into a practical to understand the Spring TestPropertySource example.
1. Introduction
@TestPropertySource is a Spring testing annotation that allows developers to specify custom property sources for configuration properties during unit or integration tests.
1.1 Advantages
- Customized Property Injection: Enables developers to inject specific property values for testing scenarios. Overrides or supplements the default configuration without altering the main application properties.
- Isolation and Controlled Testing: Ensures isolated and controlled testing environments by providing specific configurations for each test case. Enhances predictability and reliability of tests.
- Flexible Configuration: Supports loading properties from various sources such as files, inlined properties, or even environment variables. Provides flexibility in configuring test-specific properties.
- Property Source Priority: Allows multiple
@TestPropertySource
annotations and the properties are applied in the order of declaration. Developers can override properties hierarchically for more granular control.
1.2 Disadvantages
- Complexity for Simple Cases: For simple test cases, using
@TestPropertySource
might be overkill and add unnecessary complexity. - Potential for Code Duplication: If not managed carefully, using this annotation across multiple test classes may lead to duplicated property configurations.
- Dependency on External Configurations: If tests rely heavily on external property configurations, changes in those external configurations may inadvertently impact test results.
2. Spring TestPropertySource Example
Here is a spring boot example to understand the annotation. We will primarily focus on the annotation concept and leave the rest of the classes for brevity.
2.1 Create a Spring Boot Project and Add Dependencies
You can use the Spring Initializr to generate a basic Spring Boot project with the necessary dependencies. Here’s a list of Maven dependencies you should add to your Spring Boot project (pom.xml
) for this tutorial.
pom.xml
<dependencies> <!-- Spring Boot Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!-- Spring Boot Starter Test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- JUnit 5 for Testing --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.8.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.8.2</version> <scope>test</scope> </dependency> </dependencies>
2.2 Create a Service class
Create a service class. The service class has one method responsible for returning the appMessage
value. The value of the variable will be read from the properties file with the help of @Value
annotation.
Make note that the key and its value are specified in the src/main/resources/application.properties
file.
MyService.java
package com.jcg.example; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @Service public class MyService { @Value("${app.message}") private String appMessage; public String getAppMessage() { return appMessage; } }
3. Test with the @TestPropertySource
This is the JUnit 5 test class that uses the @TestPropertySource
annotation to load the properties for the MyService
object.
MySpringBootTest.java
package com.jcg.example; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; import static org.junit.jupiter.api.Assertions.assertEquals; @ExtendWith(SpringExtension.class) @SpringBootTest(classes = MyTestConfig.class) @TestPropertySource(locations = "classpath:test.properties") public class MySpringBootTest { @Autowired private MyService myService; @Test public void testAppMessage() { String actualMessage = myService.getAppMessage(); assertEquals("Hello from test.properties", actualMessage); } }
The properties will be loaded from the test.properties
file present in the src/test
folder.
test.properties
app.message=Hello from test.properties
3.1 @TestPropertySource Inline Properties
If you prefer using the inline method for specifying properties, the @TestPropertySource
annotation offers a convenient way to include inline properties directly within the annotation itself. This functionality becomes particularly beneficial when you wish to declare test-specific properties directly in your test class, eliminating the need for an additional properties file. Consider the following snippet as an illustration:
MyInlinePropertiesTest.java
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; import static org.junit.jupiter.api.Assertions.assertEquals; @ExtendWith(SpringExtension.class) @SpringBootTest @TestPropertySource(properties = {"app.message=Hello from inline properties"}) public class MyInlinePropertiesTest { @Value("${app.message}") private String appMessage; @Test public void testAppMessage() { assertEquals("Hello from inline properties", appMessage); } }
In this example, the utilization of the @TestPropertySource
annotation is demonstrated with the inclusion of the properties
attribute, providing a means to define inline properties directly within the annotation. Within the MyInlinePropertiesTest
class, a singular property, namely app.message
, is specified. The subsequent test method then verifies that the property injected aligns with the expected value.
This approach is handy for small projects or cases where you prefer to keep test-specific properties directly within the test class for better visibility and maintainability.
4. Conclusion
In conclusion, the @TestPropertySource
annotation in Spring provides a valuable tool for customizing property configurations during unit and integration tests. It offers developers the ability to inject specific property values, ensuring isolated and controlled testing environments without affecting the main application’s configuration. This annotation enhances flexibility, allowing for the seamless adjustment of test scenarios through the overriding or supplementation of properties. While beneficial for complex test cases, it’s important to use @TestPropertySource
judiciously, as it may introduce unnecessary complexity for simpler scenarios. Careful management of configurations, consideration of potential code duplication, and awareness of external dependencies are essential for leveraging this annotation effectively. Overall, @TestPropertySource
empowers developers to tailor testing environments, contributing to the creation of robust and reliable Spring applications.
5. Download the Project
This was a tutorial to understand @TestPropertySource
annotation in a Spring example.
You can download the full source code of this example here: Spring @TestPropertySource example