Home > database >  Mockito is returning "java.lang.IllegalArgumentException: URI is not absolute" in RestTemp
Mockito is returning "java.lang.IllegalArgumentException: URI is not absolute" in RestTemp

Time:01-29

Mockito is returning "java.lang.IllegalArgumentException: URI is not absolute" in RestTemplate.exchange. I am not sure why this is happening because it seems I am mocking the restTemplate properly and since I am seeing that exception, it seems that RestTemplate is not a mock.

Here is my class

@Component
public class RestTemplateWrapper {
  private static final Logger LOGGER = LoggerFactory.getLogger(RestTemplateWrapper.class);
  
  public <T> ResponseEntity<T> callWebServiceGET(String url,HttpEntity<?> httpEntity,
      ParameterizedTypeReference<T> parameterizedTypeReference) {

    RestTemplate restTemplate = new RestTemplate();
    ResponseEntity<T> response=null;
    LOGGER.trace("Entered callWebServiceGET");
    LOGGER.info("Calling WebService {}", url);
    try {
      response=restTemplate.exchange(url, HttpMethod.GET, httpEntity, parameterizedTypeReference);
    } catch (HttpClientErrorException e) {
      if (HttpStatus.NOT_FOUND.equals(e.getStatusCode())) {
        LOGGER.error("Service Unavailable - Code 404 returned. "   url   e.getMessage());
      } else if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
        LOGGER.error("Token Expired- Code 401 returned. "   e.getMessage());
      } else if (HttpStatus.BAD_REQUEST.equals(e.getStatusCode())) {
        LOGGER.error("Bad Input, 400 returned.{} {} ", url , e.getMessage(), e);
      } else {
        LOGGER.error("WEB Service Failure. "   e.getMessage());
      }
    }
    return response;
  }

}

And here is my TestCase:

@PrepareForTest({RestTemplateWrapper.class})
public class RestTemplateWrapperTest  {
  
  @Mock
  private RestTemplate mockRestTemplate;
  @InjectMocks
  private RestTemplateWrapper webUtils;
  @Before
  public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
  }
  @Test
  public void callWebServiceGET_OK()  {
    HttpEntity<String> httpEntity= new ResponseEntity<>(HttpStatus.OK);
    ResponseEntity<String> entityResponse=new ResponseEntity<>("MOCK_RESPONSE", HttpStatus.OK);
    when(mockRestTemplate.exchange(eq("/objects/get-objectA"), eq(HttpMethod.GET), eq(httpEntity),any(
        ParameterizedTypeReference.class))).thenReturn(
        entityResponse);
    ResponseEntity<String> mockResponse= webUtils.callWebServiceGET("",null,  new ParameterizedTypeReference<String>(){
    });
    //verify(mockRestTemplate,times(1)).exchange(Matchers.anyString(), Matchers.any(), Matchers.any());
     Assert.assertEquals("MOCK_RESPONSE",mockResponse.getBody());
  }
  
}

The response:

URI is not absolute
java.lang.IllegalArgumentException: URI is not absolute
    at java.net.URI.toURL(URI.java:1088)
    at org.springframework.http.client.SimpleClientHttpRequestFactory.createRequest(SimpleClientHttpRequestFactory.java:145)
    at org.springframework.http.client.support.HttpAccessor.createRequest(HttpAccessor.java:87)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:727)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:666)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:604)
    at com.project.di.tp.purchaseorderservice.utils.RestTemplateWrapper.callWebServiceGET(RestTemplateWrapper.java:29)
    at com.project.di.tp.purchaseorderservice.utils.RestTemplateWrapperTest.callWebServiceGET_OK(RestTemplateWrapperTest.java:51)

Any idea about how to solve this issue? I have been trying like 4 hours.

CodePudding user response:

Although it is not stated explicitly in the JavaDocs it is the case that you have to provide an absolute URL there.

This is because you do nowhere provide a base URL where a relative URL would be relative to. You could not enter "/objects/get-objectA" as URL in your browser either.

So I would suggest that you use something like "http://example.com/objects/get-objectA" instead for the first parameter:

when(mockRestTemplate.exchange(
        eq("http://example.com/bla"), 
        eq(HttpMethod.GET), 
        isNull(HttpEntity.class), 
        any(ParameterizedTypeReference.class))).
    thenReturn(entityResponse);

ResponseEntity<String> mockResponse =
    webUtils.callWebServiceGET(
        "http://example.com/bla", 
        null, 
        new ParameterizedTypeReference<String>(){});

Please note that the call to webUtils.callWebServiceGET with given parameters would not make Mockito return the wanted answer, so I changed for one the URL in the call to the absolute URL you are expecting in the Mockito.when and also changed the parameter expected there to be a typed null (typed to match the method signature).

CodePudding user response:

I found the solution, it seems the problem is that my class is RestTemplateWrapper is creating a instance inside callWebServiceGET therefore mockito can`t mock that object. If if set the object outside the method, it works but I dont want to do that.

Is there any way to mock a object that is inside a method?

  • Related