spring

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.

Download
You can download the full source code of this example here: Spring @TestPropertySource example

Yatin

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button