JUnit 4 เปรียบเทียบชุด


102

คุณจะยืนยันความเท่าเทียมกันของCollectionองค์ประกอบอย่างรวบรัดได้อย่างไรโดยเฉพาะ a Setใน JUnit 4



คุณกำลังพยายามยืนยันว่าทั้งสองชุดมีค่าเท่ากัน (มีองค์ประกอบเดียวกัน) หรือว่าสององค์ประกอบของชุดเดียวกันมีค่าเท่ากัน?
Bill the Lizard

ฉันต้องการดูว่าองค์ประกอบของสองชุดนั้นเท่ากัน
Eqbal

คำตอบ:


103

คุณสามารถยืนยันว่าทั้งสองSets มีค่าเท่ากันกับอีกคนหนึ่งซึ่งเรียกวิธีการSet equals()

public class SimpleTest {

    private Set<String> setA;
    private Set<String> setB;

    @Before
    public void setUp() {
        setA = new HashSet<String>();
        setA.add("Testing...");
        setB = new HashSet<String>();
        setB.add("Testing...");
    }

    @Test
    public void testEqualSets() {
        assertEquals( setA, setB );
    }
}

สิ่งนี้@Testจะผ่านไปหากสองSets มีขนาดเท่ากันและมีองค์ประกอบเดียวกัน


7
สิ่งนี้ไม่ได้แสดงผลลัพธ์ที่ดีมากในรายงาน หาก toStrings ของคุณกำหนดไว้อย่างชัดเจนจะดีกว่า แต่ก็ยังไม่ดี (ความแตกต่างเล็กน้อยสามารถลงเอยด้วยหน้าข้อความ)
Bill K

อืมทำไมฉันถึงได้: java.lang.AssertionError: ที่คาดไว้: java.util.Hashtable <{CompanyName = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Category = AvrIfd, QuoteId = 4342740204922826 Company = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Category = AvrIfd, QuoteId = 4342740204922826921}>
Giovanni Botta

3
@Giodude คุณมีequalsและhashCodeนำไปใช้ในคลาสที่คุณจัดเก็บไว้ใน Hashtable หรือไม่?
Bill the Lizard

อย่างที่คุณเห็นสิ่งเหล่านี้เป็นเพียงสตริงและแบบยาว ... ฉันกำลังทดสอบ Avro เพื่อทำให้เป็นอนุกรมและยกเลิกการทำให้เป็นอนุกรมของแผนที่และนั่นคือผลลัพธ์ ฉันคิดว่าต้องมีบางอย่างที่น่ากลัวเกิดขึ้นกับวิธีที่สตริงถูกทำให้เป็นอนุกรมและไม่ต่ออนุกรมซึ่งทำให้การทดสอบล้มเหลว แต่ดูเหมือนว่าฉันจะไม่พบปัญหา
Giovanni Botta

ไม่ได้ผลสำหรับฉันแม้ว่าฉันจะเปรียบเทียบ HashSet <Long> สองตัว คำตอบ @MattFriedman ใช้งานได้จริงสำหรับกรณีการใช้งานของฉัน
bluecollarcoder

46

Apache ร่วมกันช่วยเหลืออีกครั้ง

assertTrue(CollectionUtils.isEqualCollection(coll1, coll2));

ใช้งานได้เหมือนมีเสน่ห์ ฉันไม่รู้ว่าทำไม แต่ฉันพบว่าคอลเล็กชันต่อไปนี้assertEquals(coll1, coll2)ไม่ได้ผลเสมอไป ในกรณีที่ล้มเหลวสำหรับฉันฉันมีสองคอลเล็กชันที่ได้รับการสนับสนุนโดยชุด ทั้งแฮมเครสต์และจูนิทไม่ยอมบอกว่าคอลเลกชันเท่ากันแม้ว่าฉันจะรู้ว่ามันเป็น การใช้ CollectionUtils จะทำงานได้อย่างสมบูรณ์


20
นี่เป็นเรื่องเล็กน้อยจริงๆส่วนที่ยุ่งยากคือการระบุความแตกต่างให้กับผู้โทรอย่างชัดเจน
Bill K

1
คำตอบที่ยอมรับคือคำตอบที่ดีสำหรับคำถามเดิม (การทดสอบหน่วยโดยเฉพาะสำหรับสองชุด) แต่คำตอบนี้กับ CollectionUtils คิดว่าเป็นคำตอบที่ดีกว่าสำหรับกรณีทั่วไปส่วนใหญ่ ฉันไม่สามารถเปรียบเทียบคอลเล็กชันและชุดได้เว้นแต่จะใช้ CollectionUtils
เจ

16

กับแฮมเครสต์ :

assertThat(s1, is(s2));

ด้วยการยืนยันธรรมดา:

assertEquals(s1, s2);

หมายเหตุ: เสื้อเท่ากับ () วิธีการของระดับชุดคอนกรีตถูกนำมาใช้


1
ฉันชอบวิธีนี้เนื่องจาก Hamcrest มาพร้อมกับ JUnit 4 ดังนั้นจึงไม่จำเป็นต้องมีไลบรารีอื่น ๆ
JRSofty

2
ซึ่งอาจใช้ไม่ได้เมื่อชุดมีประเภทต่างๆ
Hans-Peter Störr

7

กรณีที่น่าสนใจอย่างยิ่งคือเมื่อคุณเปรียบเทียบ

   java.util.Arrays$ArrayList<[[name,value,type], [name1,value1,type1]]> 

และ

   java.util.Collections$UnmodifiableCollection<[[name,value,type], [name1,value1,type1]]>

จนถึงตอนนี้ทางออกเดียวที่ฉันเห็นคือเปลี่ยนทั้งคู่เป็นชุด

assertEquals(new HashSet<CustomAttribute>(customAttributes), new HashSet<CustomAttribute>(result.getCustomAttributes()));

หรือฉันสามารถเปรียบเทียบองค์ประกอบตามองค์ประกอบ


จริงๆแล้วมีวิธีแก้ปัญหาหลายวิธีสำหรับคำตอบอื่น ๆ ชุดเป็นเรื่องที่น่าเสียดายเล็กน้อยสำหรับเรื่องนี้เนื่องจากไม่สนใจคำสั่งซื้อ บางที ArrayList?
Hans-Peter Störr

4

เป็นวิธีการเพิ่มเติมที่ใช้อาร์เรย์ ... คุณสามารถพิจารณาใช้การยืนยันอาร์เรย์แบบไม่เรียงลำดับใน junitx แม้ว่าตัวอย่าง Apache CollectionUtils จะใช้งานได้ แต่ก็มีส่วนขยายการยืนยันที่มั่นคงเช่นกัน:

ผมคิดว่า

ArrayAssert.assertEquivalenceArrays(new Integer[]{1,2,3}, new Integer[]{1,3,2});

วิธีการจะอ่านได้ง่ายขึ้นและสามารถแก้ไขข้อบกพร่องได้มากขึ้นสำหรับคุณ (Collections ทั้งหมดรองรับ toArray () ดังนั้นจึงควรใช้เมธอด ArrayAssert ได้ง่ายพอสมควร

แน่นอนข้อเสียคือ junitx เป็นไฟล์ jar เพิ่มเติมหรือรายการ maven ...

 <dependency org="junit-addons" name="junit-addons" rev="1.4"/>

2

ตรวจสอบบทความนี้ ตัวอย่างหนึ่งจากที่นั่น:

@Test  
public void listEquality() {  
    List<Integer> expected = new ArrayList<Integer>();  
    expected.add(5);  

    List<Integer> actual = new ArrayList<Integer>();  
    actual.add(5);  

    assertEquals(expected, actual);  
}  

ลิงค์สั้น ๆ แต่ยอดเยี่ยมอธิบายได้อย่างรวดเร็วว่าคุณสามารถทำอะไรกับ Junit4-
Johannes

1
ลิงค์เสีย มีโอกาสใดบ้างที่คุณจะพบเวอร์ชันที่เก็บถาวรทางออนไลน์หรือสรุปเนื้อหา
pzp

1

ใช้ Hamcrest:

assertThat( set1, both(everyItem(isIn(set2))).and(containsInAnyOrder(set1)));

วิธีนี้ใช้ได้เช่นกันเมื่อชุดมีประเภทข้อมูลที่แตกต่างกันและรายงานเกี่ยวกับความแตกต่างแทนที่จะล้มเหลว


2
การนำเข้าสำหรับ isIn คืออะไร? IntelliJ ไม่สามารถแก้ไขการนำเข้าด้วยแพ็คเกจแฮมเครตใด ๆ
fabien

0

หากคุณต้องการตรวจสอบว่ารายการหรือชุดมีชุดของค่าเฉพาะหรือไม่ (แทนที่จะเปรียบเทียบกับคอลเล็กชันที่มีอยู่แล้ว) โดยทั่วไปวิธีการ toString ของคอลเลกชันนั้นมีประโยชน์:

String[] actualResult = calltestedmethod();
assertEquals("[foo, bar]", Arrays.asList(actualResult).toString());

List otherResult = callothertestedmethod();
assertEquals("[42, mice]", otherResult.toString());

ซึ่งสั้นกว่าการสร้างคอลเล็กชันที่คาดไว้ครั้งแรกเล็กน้อยและเปรียบเทียบกับคอลเล็กชันจริงและง่ายต่อการเขียนและแก้ไข

(เป็นที่ยอมรับว่านี่ไม่ใช่วิธีการที่สะอาดโดยเฉพาะและไม่สามารถแยกแยะองค์ประกอบ "foo, bar" จากสององค์ประกอบ "foo" และ "bar" ได้ แต่ในทางปฏิบัติฉันคิดว่าสิ่งสำคัญที่สุดคือการเขียนแบบทดสอบที่ง่ายและรวดเร็ว มิฉะนั้นนักพัฒนาจำนวนมากจะไม่กดโดยไม่ต้องกด)


สิ่งนี้ทำให้ผลลัพธ์ของการทดสอบหน่วยของคุณขึ้นอยู่กับการใช้ toString จากรายการ หากพวกเขาตัดสินใจที่จะเปลี่ยนการจัดรูปแบบการทดสอบหน่วยจะไม่ทำงานอีกต่อไป ฉันจะไม่คิดว่าสิ่งนี้ปลอดภัย
Laurens Op 't Zandt

@ LaurensOp'tZandt คุณหมายถึง Oracle เปลี่ยนรูปแบบของ Collection.toList ()? นั่นจะไม่เกิดขึ้นอย่างแน่นอน อย่างไรก็ตามคุณใช่ไหมที่ไม่สะอาดเป็นพิเศษ แต่ในทางปฏิบัติความประทับใจของฉันที่สำคัญที่สุดคือการเขียนข้อสอบนั้นง่ายมาก
Hans-Peter Störr

ฉันเห็นด้วยฉันคิดว่าวิธี toString ไม่น่าจะเกิดขึ้นได้ ดังนั้นมันอาจจะทำงานต่อไป ฉันแค่อยากจะชี้ให้เห็นว่ามันไม่ใช่วิธีที่สะอาดมากนัก แต่แท้จริงแล้วมันง่ายมาก ปัญหาหนึ่งที่เกิดขึ้นคือเมื่อเปรียบเทียบชุด เนื่องจากไม่รับประกันการสั่งซื้อ
Laurens Op 't Zandt

0

ฉันชอบวิธีแก้ปัญหาของ Hans-Peter Störr ... แต่ฉันคิดว่ามันไม่ถูกต้องนัก น่าเศร้าที่containsInAnyOrderไม่ยอมรับCollectionobjetcs เพื่อเปรียบเทียบกับ ดังนั้นจึงจะต้องมีCollectionของMatchers:

assertThat(set1, containsInAnyOrder(set2.stream().map(IsEqual::equalTo).collect(toList())))

การนำเข้า ได้แก่ :

import static java.util.stream.Collectors.toList;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertThat;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.