How to mock @Value field in Spring Boot

How to mock @Value field in Spring Boot

The @Value annotation injects externalized properties into a Spring Boot application. The field’s value is usually read from the application.properties or application.yml file. While @Value eases the reading of externalized properties, it can present challenges during testing. In this article, we cover how to mock the @Value field in Spring Boot during both integration and unit testing.

Overwrite @Value During Integration Testing

To mock, or more precisely, overwrite the @Value during integration testing, you can create a separate resources directory, add an application.properties file, and set a desired value in it. For instance, let’s assume we have the following property:

api.endpoint=https://eris.madadipouya.com/v1/weather/currentbyip

We want to overwrite this value during integration testing. To achieve this, as mentioned, we only need to create the application.properties file and then set the desired value:

api.endpoint=https://dummyjson.com/test

During testing, you can access the property as usual.

@SpringBootTest
class WeatherApiIntegrationTest {

  @Autowired
  private WeatherApi weatherApi;

  @Test
  void testGetWeatherApiEndpointAddress() {
    String result = weatherApi.getApiEndpoint();

    assertEquals("https://dummyjson.com/test", result);
  }
}

Mock @Value During Unit Testing

It is also possible to mock the @Value field during unit testing, but it is a bit trickier.

To achieve that, we need to use ReflectionTestUtils as shown below:

  @InjectMocks
  private WeatherApi weatherApi;

  @BeforeEach
  void initialize() {
    ReflectionTestUtils.setField(weatherApi, "apiEndpoint", "https://weather-api.com");
  }

The first argument is the object under test. The second argument is the name of the field whose value we aim to overwrite, and the last argument is the desired value. Here’s the full example:

@ExtendWith(MockitoExtension.class)
class WeatherApiTest {

  @InjectMocks
  private WeatherApi weatherApi;

  @BeforeEach
  void initialize() {
    ReflectionTestUtils.setField(weatherApi, "apiEndpoint", "https://weather-api.com");
  }

  @Test
  void testGetWeatherApiEndpointAddress() {
    String result = weatherApi.getApiEndpoint();

    assertEquals("https://weather-api.com", result);
  }
}

Conclusion

In this article, we covered how to mock the @Value field in Spring Boot during integration and unit testing. For integration testing, you only need to create a test application.properties file. However, unit testing requires explicitly overwriting the value using the ReflectionTestUtils class. As always, the tutorial’s code is available on the Geeky Hacker GitHub repository.

Inline/featured images credits

2348 2363 2387