I am trying to get some junit tests with Mockito to work in a SprinBoot application.
Now my Service has some variable that gets filled from the application.properties
by means of @Value
annotation:
@Component
@Slf4j
public class FeatureFlagService {
@Autowired
RestTemplate restTemplate;
@Value("${url.feature_flags}")
String URL_FEATURE_FLAGS;
// do stuff
}
I am trying to test this by using TestPropertySource
like so:
@ExtendWith(MockitoExtension.class)
@TestPropertySource(properties = { "${url.feature_flags} = http://endpoint" })
class FeatureFlagServiceTests {
@Mock
RestTemplate restTemplate;
@InjectMocks
FeatureFlagService featureFlasgService;
@Test
void propertyTest(){
Assertions.assertEquals(featureFlasgService.URL_FEATURE_FLAGS, "http://endpoint");
}
However the property does not get filled and remains null
.
There are a bunch of tpoics on this, but I have not been able to piece together a solution. I saw solutions suggesting @SpringBootTest
, but then it seems to want to do an integration test, spinning up the service, which fails because it can not connect to DB. So that is not what I am looking for.
I also saw solutions suggesting I make a PropertySourcesPlaceholderConfigurer
bean. I tried that by putting:
@Bean
public static PropertySourcesPlaceholderConfigurer propertiesResolver() {
return new PropertySourcesPlaceholderConfigurer();
}
In my Application.java
. But that is not working / not enough. I am not sure if I was supposed to do that differently, or if there is more there that I do not know.
Please advice.
You can use @SpringBootTest
without running the whole application by passing it the class that contains the @Value
but you have to use Spring's extension @ExtendWith({SpringExtension.class})
which is included inside @SpringBootTest
and by that using Spring's MockBean
instead of @Mock
and @Autowired
for autowiring the bean like this:
@SpringBootTest(classes = FeatureFlagService.class)
class FeatureFlagServiceTests {
@MockBean
RestTemplate restTemplate;
@Autowired
FeatureFlagService featureFlasgService;
@Test
void propertyTest(){
Assertions.assertEquals(featureFlasgService.URL_FEATURE_FLAGS, "http://endpoint");
}
I recommend you to try this approach. Just need a slightly refactoring and add a package-private constructor to your FeatureFlagService
.
FeatureFlagService.java
@Component
@Slf4j
public class FeatureFlagService {
private final RestTemplate restTemplate;
private final String URL_FEATURE_FLAGS;
// package-private constructor. test-only
FeatureFlagService(RestTemplate restTemplate, @Value("${url.feature_flags}") String flag) {
this.restTemplate = restTemplate;
this.URL_FEATURE_FLAGS = flag;
}
// do stuff
}
Then prepare your mocks and url, and inject them by the constructor-injection
.
FeatureFlagServiceTests.java
public class FeatureFlagServiceTests {
private FeatureFlagService featureFlagService;
@Before
public void setup() {
RestTemplate restTemplate = mock(RestTemplate.class);
// when(restTemplate)...then...
String URL_FEATURE_FLAGS = "http://endpoint";
featureFlagService = new FeatureFlagService(restTemplate, URL_FEATURE_FLAGS);
}
@Test
public void propertyTest(){
Assertions.assertEquals(featureFlasgService.getUrlFeatureFlags(),
"http://endpoint");
}
}
The significant advantage is, your FeatureFlagServiceTests
becomes very simple to read and trivial to test. You don't need magic annotation of Mockito anymore.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.