Mock an Autowired Value Field in Spring with Junit 5
Mock @Value
In this example I am going to show you how to mock an autowired field in Spring boot framework with Junit 5.
When you use@Value annotation in Spring beans to read the value from properties file and later when you want to perform Junit test then you also need to pass value for this autowired field value otherwise you won’t be able to cover your testing. Read if you need Junit 4 version of testing for Spring’s autowired field value.Now it is really cumbersome to place a properties file and read configuration values into those fields. Therefore Spring provides an easy way to set values to aitowired @Value fields using RefectionTestUtils‘s setField() method.
Actually you need to pass three parameters as values into setField() method. The first parameter’s value indicates the class instance for which you want to set value to the autowired field. The second parameter’s value indicates the class attribute name for which you want to set the value. The final or third parameter’s value indicates the actual value that will be set to the class attribute.
Prerequisites
Java 8/12/19, Maven 3.6.3/3.8.5, Spring Boot 2.4.0 – 2.4.5/3.1.3
Project Setup
You can create a maven based project in your favorite IDE or tool. The name of the project is spring-mock-autowired-field-value-junit-5.
For the maven project you can use the following pom.xml file:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.roytuts</groupId>
<artifactId>spring-mock-autowired-field-value-junit-5</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>19</maven.compiler.source>
<maven.compiler.target>19</maven.compiler.target>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.3</version>
</parent>
<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>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-engine</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Spring Service
I am creating a simple Spring service class that has an autowired @Value annotated field that is set to a value from properties file (src/main/resources/application.properties). This @Value annotated field will be mocked in the Junit class later in this example.
@Service
public class SpringServiceAutowiredField {
@Value("${security.key}")
private String securityKey;
public void getValue() {
System.out.println("${security.key}: " + securityKey);
}
} Properties File
I am creating a properties file src/main/resources/application.properties file with the following key/value pair.
security.key=SecurityKey As I have created Spring boot application so first I will verify this autowired @Value field using main class.
Spring Boot Main Class
In Spring Boot application a class with main method and @SpringBootApplication annotation is enough to run the application. I am using CLI version of Spring boot application.
@SpringBootApplication
public class SpringMockAutowiredValueApp implements CommandLineRunner {
@Autowired
private SpringServiceAutowiredField service;
public static void main(String[] args) {
SpringApplication.run(SpringMockAutowiredValueApp.class, args);
}
@Override
public void run(String... args) throws Exception {
service.getValue();
}
} Testing the @Value Field
Just executing the above main class will give you the following output in the concole.
${security.key}: SecurityKey Next let’s move on to creating Junit test class that will test the @Value annotated field.
Junit Class
The following class in created under src/test/java folder.
@ExtendWith(MockitoExtension.class)
public class SpringAutowiredValueTest {
@Mock
private SpringServiceAutowiredField service;
@BeforeEach
public void setUp() {
ReflectionTestUtils.setField(service, "securityKey", "It's a security key");
}
@Test
public void testAutowiredValueField() {
service.getValue();
Mockito.verify(service, Mockito.times(1)).getValue();
}
} Generally when you mock such field that is being used for entire class. Therefore, you need to initialize such field only once or before each test case executed. So if you need to initialize only once then you can put it using @BeforeAll annotation and if you need to execute before each test method then you need to put it using @BeforeEach annotation.
Here in this example I have initialized the field using @BeforeEach annotation because I have only one test case.
Here you run the class with @ExtendWith(MockitoExtension.class) because you do not want to run integration test but mock test.
Notice how I do initialize the autowired @Value annotated field using ReflectionTestUtils.
I finally test the service class’s method and verify whether the method executed at least once using Junit’s verify() method.
Testing the Junit Test Class
Now run the Junit class, your Junit test will pass.

You will get the following output in the console.
Setting field 'securityKey' of type [null] on target object [service] or target class [class com.roytuts.spring.mock.autowired.field.value.junit.SpringServiceAutowiredField$MockitoMock$1287953113] to value [It's a security key] I have set the new value to the security key and displayed using getValue() method.
No comments
Leave a comment