Dado el siguiente ejemplo (usando JUnit con los emparejadores Hamcrest):
Map<String, Class<? extends Serializable>> expected = null;
Map<String, Class<java.util.Date>> result = null;
assertThat(result, is(expected));
Esto no se compila con la assertThat
firma del método JUnit de:
public static <T> void assertThat(T actual, Matcher<T> matcher)
El mensaje de error del compilador es:
Error:Error:line (102)cannot find symbol method
assertThat(java.util.Map<java.lang.String,java.lang.Class<java.util.Date>>,
org.hamcrest.Matcher<java.util.Map<java.lang.String,java.lang.Class
<? extends java.io.Serializable>>>)
Sin embargo, si cambio la assertThat
firma del método a:
public static <T> void assertThat(T result, Matcher<? extends T> matcher)
Entonces la compilación funciona.
Entonces tres preguntas:
- ¿Por qué no se compila exactamente la versión actual? Aunque entiendo vagamente los problemas de covarianza aquí, ciertamente no podría explicarlo si tuviera que hacerlo.
- ¿Hay algún inconveniente en cambiar el
assertThat
método aMatcher<? extends T>
? ¿Hay otros casos que se romperían si hicieras eso? - ¿Tiene algún sentido la genéricaización del
assertThat
método en JUnit? LaMatcher
clase no parece requerirlo, ya que JUnit llama al método de coincidencias, que no está escrito con ningún genérico, y solo parece un intento de forzar una seguridad de tipo que no hace nada, yaMatcher
que en realidad no lo hará. coinciden, y la prueba fallará independientemente. No hay operaciones inseguras involucradas (o eso parece).
Como referencia, aquí está la implementación JUnit de assertThat
:
public static <T> void assertThat(T actual, Matcher<T> matcher) {
assertThat("", actual, matcher);
}
public static <T> void assertThat(String reason, T actual, Matcher<T> matcher) {
if (!matcher.matches(actual)) {
Description description = new StringDescription();
description.appendText(reason);
description.appendText("\nExpected: ");
matcher.describeTo(description);
description
.appendText("\n got: ")
.appendValue(actual)
.appendText("\n");
throw new java.lang.AssertionError(description.toString());
}
}