Dado o seguinte exemplo (usando o JUnit com os correspondentes do Hamcrest):
Map<String, Class<? extends Serializable>> expected = null;
Map<String, Class<java.util.Date>> result = null;
assertThat(result, is(expected));
Isso não é compilado com a assertThat
assinatura do método JUnit de:
public static <T> void assertThat(T actual, Matcher<T> matcher)
A mensagem de erro do compilador é:
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>>>)
No entanto, se eu alterar a assertThat
assinatura do método para:
public static <T> void assertThat(T result, Matcher<? extends T> matcher)
Então a compilação funciona.
Então, três perguntas:
- Por que exatamente a versão atual não é compilada? Embora eu entenda vagamente as questões de covariância aqui, certamente não conseguiria explicar se fosse necessário.
- Existe alguma desvantagem na alteração do
assertThat
método paraMatcher<? extends T>
? Existem outros casos que quebrariam se você fizesse isso? - Existe algum ponto para a generalização do
assertThat
método no JUnit? AMatcher
classe parece não exigir isso, já que o JUnit chama o método de correspondências, que não é digitado com nenhum genérico, e parece uma tentativa de forçar uma segurança de tipo que não faz nada, pois aMatcher
vontade simplesmente não corresponder e o teste falhará independentemente. Nenhuma operação insegura envolvida (ou assim parece).
Para referência, aqui está a implementação 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());
}
}