이 (Hamcrest 매처 (matcher)와 사용의 JUnit) 다음의 예를 감안할 때 :Java generics는 언제 <T> 대신 <? extends T>을 필요로하며 전환의 단점이 있습니까?
Map<String, Class<? extends Serializable>> expected = null;
Map<String, Class<java.util.Date>> result = null;
assertThat(result, is(expected));
이의 JUnit을 assertThat
메소드 서명과 함께 컴파일되지 않습니다 :
public static <T> void assertThat(T actual, Matcher<T> matcher)
컴파일러 오류 메시지입니다 :
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>>>)
그러나 assertThat
메서드 서명을 다음과 같이 변경하면
public static <T> void assertThat(T result, Matcher<? extends T> matcher)
그러면 컴파일이 작동합니다.
그래서 세 가지 질문 :
- 이유는 정확히 현재 버전은 컴파일되지 않습니다? 내가 여기서 공분산 문제를 모호하게 이해하고 있지만 분명히 설명 할 수는 없습니다.
Matcher<? extends T>
에assertThat
방법을 변경하는 어떤 단점은 - 있습니까? 당신이 그렇게했다면 어쩔 수없는 다른 경우가 있습니까?
- JUnit에서
assertThat
메서드를 제네릭 화하는 데 요점이 있습니까? JUnit을 어떤 일반적으로 입력되지 않은 일치 메서드를 호출, 그냥 아무것도하지 않는 형태의 안전을 강제하려는 시도처럼 보인다 때문에Matcher
클래스는, 그것을 필요로하지 않는 것Matcher
처럼하지 않습니다 사실 일치하고, 테스트는 상관없이 실패합니다. 안전하지 않은 작업이 포함되어 있지 않습니다 (또는 그렇게 보입니다).
는 참고로, 여기 assertThat
의 JUnit을 구현 한 것입니다 :
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());
}
}
링크가 매우 유용합니다 (제네릭, 상속 및 하위 유형). http://docs.oracle.com/javase/tutorial/java/generics/inheritance.html –