2012-06-08 16 views
9

Estoy escribiendo un caso de prueba que usa un java.beans.PropertyDescriptor usando Mockito, y quiero simular el comportamiento de getPropertyType() para devolver un objeto arbitrario Class<?> (en mi case, String.class). Normalmente, me gustaría hacer que con sólo invocar:Un extraño caso de borde genérico con Mockito.when() y la inferencia de tipo genérico

// we already did an "import static org.mockito.Mockito.*" 
when(mockDescriptor.getPropertyType()).thenReturn(String.class); 

Sin embargo, curiosamente, esto no se compila:

cannot find symbol method thenReturn(java.lang.Class<java.lang.String>) 

Pero cuando especifico el parámetro de tipo en lugar de depender de la inferencia:

Mockito.<Class<?>>when(mockDescriptor.getPropertyType()).thenReturn(String.class); 

todo es Hunky Dory. ¿Por qué el compilador no puede inferir correctamente el tipo de retorno de when() en este caso? Nunca tuve que especificar el parámetro antes así.

Respuesta

13

PropertyDescriptor#getPropertyType() devuelve un objeto de Class<?>, donde ? significa "este es un tipo, pero no sé lo que es". Llamemos a este tipo "X". Por lo tanto, when(mockDescriptor.getPropertyType()) crea un OngoingStubbing<Class<X>>, cuyo método thenReturn(Class<X>) solo acepta objetos de Class<X>. Pero el compilador no sabe de qué tipo es esta "X", por lo que se quejará de que haya pasado un Class de tipo. Creo que esta es la misma razón por la que el compilador se queja de llamar al add(...) en un Collection<?>.

Cuando se especifica explícitamente Class<?> para el tipo en el método when, no estamos diciendo que mockDescriptor.getPropertyType() devuelve un Class<?>, usted está diciendo que when devuelve un OngoingStubbing<Class<?>>. Luego, el compilador verifica para asegurarse de que lo que está pasando en when es de un tipo que coincide con Class<?>; desde getPropertyType() devuelve el "Class<X>" que mencioné anteriormente, por supuesto coincide con el Class<?> que ha especificado.

Así que, básicamente

// the inferred type is Class<"some type"> 
Mockito.when(mockDescriptor.getPropertyType()) 

// the specified type is Class<"any type"> 
Mockito.<Class<?>>when(mockDescriptor.getPropertyType()) 

En mi IDE, el mensaje de error para el código original es

The method thenReturn(Class<capture#1-of ?>) in the type OngoingStubbing<Class<capture#1-of ?>> is not applicable for the arguments (Class<String>) 

Eso es capture#1-of ? la "X" que he descrito anteriormente.

Cuestiones relacionadas