Spring Testing Annotation - @TestPropertySource - Example
In this section, we will learn about @TestPropertySource annotation.
@TestPropertySource is a class level annotation. It allows us to set test properties for a specific test, taking precedence over default property sources like Java system properties, operating system's environments etc. So the test property files or inlined properties can be used to override properties defined in system and application property sources.
If we don't want to use a file, we can specify inlined properties. The inlined properties loaded from @TestPropertySource have higher precedence over the properties loaded from resource locations.
1. @TestPropertySource Property file location
@SpringBootTest
@TestPropertySource("/test.properties")
class FilePropertyInjectionUnitTest {
//todo
}
}
Above we specified property file location.
2. @TestPropertySource Inline Properties
@SpringBootTest
@TestPropertySource(properties = {
"demo.app.key=4567"
})
public class PropertyInjectionUnitTest {
//todo
}
}
Above we specified inline property. You can configure multiple inline property.
3. @TestPropertySource Inline Properties and Property file location
@SpringBootTest
@TestPropertySource(locations = "/test.properties", properties = {
"demo.app.key=4567"
})
public class PropertyInjectionUnitTest {
//todo
}
}
Here we specified inline properties as well as property file location. The inlined properties loaded from @TestPropertySource have higher precedence over the properties loaded from resource locations.
4. Complete Example
Final Project Directory
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.knf.dev.demo</groupId>
<artifactId>testpropertysource-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>testpropertysource-example</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>paketobuildpacks/builder-jammy-base:latest</builder>
</image>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.properties
demo.app.username = Rahul
demo.app.key = 1234
Create MyService class
package com.knf.dev.demo.service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Value("${demo.app.username}")
private String userName;
@Value("${demo.app.key}")
private String key;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
}
Using @Value annotation we are injecting values which is loaded from application properties file to MyService class.
Application.java
package com.knf.dev.demo;
import com.knf.dev.demo.service.MyService;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application implements ApplicationRunner {
private final MyService myService;
public Application(MyService myService) {
this.myService = myService;
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(ApplicationArguments args) {
System.out.println("Username => "+ myService.getUserName());
System.out.println("key => "+ myService.getKey());
}
}
Create test.properties file
demo.app.key = 9876
While doing testing we are using this property file.
Test 1: Create FilePropertyInjectionUnitTest.java
package com.knf.dev.demo;
import com.knf.dev.demo.service.MyService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.junit.jupiter.api.Assertions.assertEquals;
@SpringBootTest
@TestPropertySource("/test.properties")
class FilePropertyInjectionUnitTest {
@Autowired
private MyService myService;
@Test
public void testMyService() {
assertEquals("Rahul", myService.getUserName());
assertEquals("9876", myService.getKey());
}
}
Here test property overrides default property source.
Test 2: Create PropertyInjectionUnitTest.java
package com.knf.dev.demo;
import com.knf.dev.demo.service.MyService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.junit.jupiter.api.Assertions.assertEquals;
@SpringBootTest
@TestPropertySource(properties = {
"demo.app.key=4567"
})
public class PropertyInjectionUnitTest {
@Autowired
private MyService myService;
@Test
public void testMyService() {
assertEquals("Rahul", myService.getUserName());
assertEquals("4567", myService.getKey());
}
}
Here inline property overrides default property source.
5. Run the test
Or you can run the test using following command:
mvn test -Dtest=FilePropertyInjectionUnitTest
mvn test -Dtest=PropertyInjectionUnitTest
or
mvn test