I have written following Junit for the method which is using rest template to call another service but the mocking is throwing URI not absolute error.
Method:
@Value("${app.prop.esso-url}")
private String essoUrl;
public ResponseEntity<String> essoCall(String token) {
ResponseEntity<String> response=null;
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Accept", MediaType.APPLICATION_JSON_VALUE);
headers.setBearerAuth(token);
HttpEntity<String> entity = new HttpEntity<>(headers);
response= restTemplate.exchange(essoUrl, HttpMethod.GET, entity,String.class);
logger.info("successfully received response.");
return response;
}
Junit:
@Autowired
private ObjectMapper objectMapper;
@InjectMocks
SecurityMsServiceImpl securityservice=new SecurityMsServiceImpl();
@Value("${app.prop.esso-url}")
private String essoUrl;
@Mock
private RestTemplate restTemplate;
@Test
void givenMockingIsDoneByMockito_whenGetIsCalled_shouldReturnMockedObject() {
ResponseEntity<String> responseEntity = new ResponseEntity<String>("success", HttpStatus.OK);
Mockito
.when(restTemplate.getForEntity(essoUrl
, String.class))
.thenReturn(responseEntity);
ResponseEntity<String> finalresponse=securityservice.essoCall("abc");
assertEquals(responseEntity, finalresponse);
}
CodePudding user response:
I see this problem time and time again:
You are constructing new instance of RestTemplate
in your method under test.
What you should do instead is to inject it into your bean, which means:
- add a field of type RestTemplate in your bean
- initialize it in constructor
- in tests, pass in mocked instance
- in prod, pass in a regular instance via Spring DI
RestTemplate is thread-safe and one instance of it is perfectly valid. See Is RestTemplate thread safe?
On top of that:
- my advice is to use constructor injection instead of field injection
- you are mixing Spring's @Autowired with Mockito's @InjectMocks. Choose if you want to test with MockitoExtension or SpringExtension and pick the appropriate set of annotations to initialize your SUT.