I'm writing a test case that uses a java.beans.PropertyDescriptor
using Mockito, and I want to mock the behavior of getPropertyType()
to return an arbitrary Class<?>
object (in my case, String.class
). Normally, I would do that by just invoking:
// we already did an "import static org.mockito.Mockito.*"
when(mockDescriptor.getPropertyType()).thenReturn(String.class);
However, oddly, this does not compile:
cannot find symbol method thenReturn(java.lang.Class<java.lang.String>)
But when I specify the type parameter instead of depending on inference:
Mockito.<Class<?>>when(mockDescriptor.getPropertyType()).thenReturn(String.class);
everything is hunky dory. Why can't the compiler correctly infer the return type of when() in this case? I have never had to specify the parameter before like that.
PropertyDescriptor#getPropertyType()
returns an object of Class<?>
, where the ?
means "this is a type, but I don't know what it is". Let's call this type "X". So when(mockDescriptor.getPropertyType())
creates an OngoingStubbing<Class<X>>
, whose method thenReturn(Class<X>)
can only accept objects of Class<X>
. But the compiler doesn't know what type this "X" is, so it will complain about you passing in a Class
of any type. I think this is the same reason the compiler complains about calling add(...)
on a Collection<?>
.
When you explicitly specify Class<?>
for the type on the when
method, you're not saying that mockDescriptor.getPropertyType()
returns a Class<?>
, you're saying that when
returns an OngoingStubbing<Class<?>>
. Then, the compiler checks to make sure whatever you're passing into when
is of a type that matches Class<?>
; since getPropertyType()
returns the "Class<X>
" I mentioned earlier, it of course matches the Class<?>
you specified.
So basically
// the inferred type is Class<"some type">
Mockito.when(mockDescriptor.getPropertyType())
// the specified type is Class<"any type">
Mockito.<Class<?>>when(mockDescriptor.getPropertyType())
In my IDE, the error message for your original code is
The method thenReturn(Class<capture#1-of ?>) in the type OngoingStubbing<Class<capture#1-of ?>> is not applicable for the arguments (Class<String>)
That capture#1-of ?
is the "X" I described above.
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