I have following service class:
@Service
public class BidServiceImpl implements BidService {
private final String apiUrl;
private final RestTemplate restTemplate;
@Autowired
public BidServiceImpl(RestTemplate restTemplate,
@Value("${api.url}") String apiUrl){
this.apiUrl = apiUrl;
this.restTemplate = restTemplate;
}
public List<Bid> findAll() {
ResponseEntity<Bid[]> responseEntity = restTemplate.getForEntity(apiUrl, Bid[].class);
Bid[] bids = responseEntity.getBody();
return Arrays.asList(bids);
}
}
and following test:
@RunWith(MockitoJUnitRunner.class)
public class TestBidService {
@InjectMocks
private BidServiceImpl bidService;
@Mock
RestTemplate restTemplate;
@Test
public void testFindAllReturnsListOfBids(){
List<Bid> b = new ArrayList<>();
Bid[] arr = new Bid[2];
arr[1] = new Bid();
arr[0] = new Bid();
ResponseEntity<Bid[]> br = new ResponseEntity<>(arr, HttpStatus.OK);
when(restTemplate.getForEntity("url",Bid[].class)).thenReturn(br);
List<Bid> bids = bidService.findAll();
Assert.assertEquals(2,bids.size());
Assert.assertTrue(bids instanceof List);
}
}
when I run the unit test, I am getting a NullPointerException
on apiUrl
. which is injected as @Value
in the my service class. The question is why it is not able to get the value from application.properties
when I run the api and hit that service method via a controller everything works fine.
Because all the @MockitoJUnitRunner
, @InjectMocks
and @Mock
are Mockito stuffs and they do not know anything about Spring. Hence they do not understand what @Value
does and will not inject its value. The spring container even do not start in you case.
If you are using spring-boot and want Spring to inject this value , you can consider using spring-boot-starter-test
starter and use its @MockBean
to configure the Mockito mock :
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestBidService {
@Autowired
private BidServiceImpl bidService;
@MockBean
RestTemplate restTemplate;
@Test
public void testFindAllReturnsListOfBids(){
///
}
}
But it is an integration test as it will start up the whole spring container , so it is slower than the true unit test.
If you want the test to run as fast as possible , don't rely on Spring to inject that value for you. Simply set up by yourself:
@RunWith(MockitoJUnitRunner.class)
public class TestBidService {
@Mock
RestTemplate restTemplate;
@Test
public void testFindAllReturnsListOfBids(){
BidServiceImpl bidService = new BidServiceImpl(restTemplate , "http://127.0.0.1/");
////
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With