I am trying to understanding how the generics work in case of Mockito.
I am trying to mock the RestTemplate
, however the following code does not compile and I don't know why:
var expectedResponse = createServiceResponse();
when(restTemplate.exchange(anyString(), any(HttpMethod.class),
Mockito.<HttpEntity<Object>>any(),
Mockito.<ServiceResponse>any().getClass(), anyMap()))
.thenReturn(ResponseEntity.ok(expectedResponse));
The compiler keeps giving me the error message:
Cannot resolve method 'thenReturn(org.springframework.http.ResponseEntity<T>)
But when I switch Mockito.<ServiceResponse>any().getClass()
with Mockito.<Class<ServiceResponse>>any()
the compilation succeeds.
Why is this happening ?
What is the difference between Mockito.<ServiceResponse>any().getClass()
and Mockito.<Class<ServiceResponse>>any()
?
They should be the same thing right ?
I mean the class of ServiceResponse
should be Class<ServiceResponse>
. Right ?
I don't have a good grasp of advanced generics so I can't understand what the compiler is doing.
Please do add some description in the answer so that I can understand why this is working the way it is suppose to.
CodePudding user response:
Only in these cases, where the compiler cannot garantuee the returned type of the method (here restTemplate.exchange
) we can use the non-type-safe equivalent syntax:
Mockito.doReturn(ResponseEntity.ok(expectedResponse))
.when(restTemplate)
.exchange(anyString(), any(HttpMethod.class),
Mockito.<HttpEntity<Object>>any(),
Mockito.<ServiceResponse>any().getClass(), anyMap()));
CodePudding user response:
What is the difference between Mockito.<ServiceResponse>any().getClass()
and Mockito.<Class<ServiceResponse>>any()?
Mockito.<ServiceResponse>any()
is an instance of ServiceResponse
. And calling getClass()
from any instance return Class<?>
. getClass()
is created to get the actual class of the instance, usually for runtime comparison.
On the other hand,
Mockito.<Class<ServiceResponse>>any()
is an instance of Class<ServiceResponse>
I mean the class of ServiceResponse should be Class. Right ?
Not really, consider following code
private void dummy(ServiceResponse response) {
System.out.println(response.getClass().equals(ServiceResponse.class));
}
You can't guarantee the output is always true, as response
can be of type CustomServiceResponse
(extending ServiceResponse)
For your problem, just use ServiceResponse.class
, simple and clear.
Further reading:
What is the difference between a.getClass() and A.class in Java?
Why does a wildcard on a generic parameter require an explicit cast?
Java: getClass() of bounded type