รับตัวอย่างต่อไปนี้ (ใช้ JUnit กับ Hamcrest matchers):
Map<String, Class<? extends Serializable>> expected = null;
Map<String, Class<java.util.Date>> result = null;
assertThat(result, is(expected));
สิ่งนี้ไม่ได้คอมไพล์ด้วยassertThat
ลายเซ็นเมธอดJUnit ของ:
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)
จากนั้นการรวบรวมก็ใช้งานได้
ดังนั้นสามคำถาม:
- ทำไมเวอร์ชั่นปัจจุบันจึงไม่คอมไพล์? แม้ว่าฉันจะเข้าใจปัญหาความแปรปรวนร่วมที่นี่ฉันไม่สามารถอธิบายได้อย่างแน่นอนถ้าฉันต้องทำ
- มีข้อเสียในการเปลี่ยน
assertThat
วิธีการMatcher<? extends T>
หรือไม่ มีกรณีอื่นอีกไหมที่จะทำให้แตกถ้าคุณทำอย่างนั้น? - มีจุดใดที่ทำให้
assertThat
วิธีการทั่วไปใน JUnit?Matcher
ระดับดูเหมือนจะไม่จำเป็นต้องใช้มันตั้งแต่ JUnit สายตรงวิธีการซึ่งไม่ได้ถูกพิมพ์โดยทั่วไปและเพียงแค่รูปลักษณ์ใด ๆ เช่นความพยายามที่จะบังคับให้มีความปลอดภัยประเภทที่ไม่ได้ทำอะไรเป็นMatcher
จะเพียงแค่ไม่ได้อยู่ในความเป็นจริง จับคู่และการทดสอบจะล้มเหลวโดยไม่คำนึงถึง ไม่มีการดำเนินการที่ไม่ปลอดภัย (หรือดูเหมือนว่า)
สำหรับการอ้างอิงนี่คือการใช้ JUnit ของ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());
}
}