JUnit 4 membandingkan Set

102

Bagaimana Anda secara ringkas menegaskan persamaan Collectionelemen, khususnya a Setdi JUnit 4?

Eqbal
sumber
2
periksa posting SO ini stackoverflow.com/questions/1086691/collectionassert-in-junit
Teja Kantamneni
Apakah Anda mencoba untuk menyatakan bahwa dua Himpunan sama satu sama lain (mengandung elemen yang sama), atau dua elemen dari Himpunan yang sama adalah sama?
Bill the Lizard
Saya perlu melihat bahwa elemen dari dua Himpunan adalah sama
Persamaan

Jawaban:

103

Anda dapat menyatakan bahwa keduanya Setsama satu sama lain, yang memanggil Set equals()metode tersebut .

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 );
    }
}

Ini @Testakan lolos jika keduanya Setberukuran sama dan mengandung elemen yang sama.

Bill the Lizard
sumber
7
Ini tidak menampilkan hasil yang sangat baik dalam laporan tersebut. Jika toString Anda didefinisikan dengan jelas, itu lebih baik, tetapi tetap tidak bagus (Perbedaan kecil dapat berakhir pada satu halaman teks)
Bill K
Uhm, kok saya dapat: java.lang.AssertionError: diharapkan: java.util.Hashtable <{CompanyName = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Category = AvrIfd, QuoteId = 43427402049228269 = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Kategori = AvrIfd, QuoteId = 4342740204922826921}>
Giovanni Botta
3
@Giodude Apakah Anda telah equalsdan hashCodemenerapkan di kelas yang Anda simpan di Hashtable Anda?
Bill the Lizard
Seperti yang Anda lihat, itu hanya string dan panjang ... Saya menguji Avro untuk membuat serial dan membatalkan serialisasi peta dan itulah hasilnya. Saya pikir pasti ada sesuatu yang mencurigakan terjadi dengan cara string diserialisasi dan dideseriisasi yang membuat pengujian gagal tetapi sepertinya saya tidak dapat menemukan masalahnya.
Giovanni Botta
Tidak berhasil untuk saya meskipun saya membandingkan dua HashSet <Long>. Jawaban @MattFriedman sebenarnya berfungsi untuk kasus penggunaan saya.
bluecollarcoder
46

Apache bersiap untuk menyelamatkan lagi.

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

Bekerja seperti pesona. Saya tidak tahu mengapa tetapi saya menemukan bahwa dengan koleksi berikut assertEquals(coll1, coll2)ini tidak selalu berfungsi. Dalam kasus di mana gagal untuk saya, saya memiliki dua koleksi yang didukung oleh Sets. Baik hamcrest maupun junit tidak akan mengatakan bahwa koleksinya sama meskipun saya tahu pasti itu sama. Menggunakan CollectionUtils bekerja dengan sempurna.

Matt Friedman
sumber
20
Ini sebenarnya sepele, bagian yang sulit adalah dengan jelas menunjukkan perbedaannya kepada penelepon
Bill K
1
Jawaban yang diterima adalah jawaban yang bagus untuk pertanyaan asli (tes unit khusus untuk dua Set) tetapi jawaban dengan CollectionUtils ini menurut saya jawaban yang lebih baik untuk kasus yang paling umum. Saya tidak dapat membandingkan Collection dan Set kecuali menggunakan CollectionUtils.
Jay
16

dengan hamcrest :

assertThat(s1, is(s2));

dengan pernyataan sederhana:

assertEquals(s1, s2);

NB: t metode equals () dari kelas himpunan beton digunakan

dfa
sumber
1
Saya lebih suka metode ini karena Hamcrest hadir dengan JUnit 4 jadi itu semua tidak perlu perpustakaan lain.
JRSofty
2
Ini mungkin tidak berfungsi jika set memiliki tipe yang berbeda.
Hans-Peter Störr
7

Kasus yang sangat menarik adalah saat Anda membandingkan

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

dan

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

Sejauh ini, satu-satunya solusi yang saya lihat adalah mengubah keduanya menjadi set

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

Atau saya bisa membandingkannya elemen demi elemen.


sumber
Sebenarnya ada beberapa solusi untuk itu yang disajikan pada jawaban lain. Set agak disayangkan untuk ini, karena mereka mengabaikan pesanan. Mungkin ArrayList?
Hans-Peter Störr
4

Sebagai metode tambahan yang berbasis array ... Anda dapat mempertimbangkan untuk menggunakan pernyataan array tak berurutan di junitx. Meskipun contoh Apache CollectionUtils akan berfungsi, ada juga paket ekstensi pernyataan yang solid di sana:

Saya pikir itu

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

pendekatan akan jauh lebih mudah dibaca dan di-debug untuk Anda (semua Koleksi mendukung toArray (), jadi seharusnya cukup mudah untuk menggunakan metode ArrayAssert.

Tentu saja kekurangannya di sini adalah, junitx adalah file jar tambahan atau entri maven ...

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

Lihat artikel ini . Satu contoh dari sana:

@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);  
}  
Roma
sumber
Link pendek tapi bagus, menjelaskan dengan sangat cepat apa yang dapat Anda lakukan dengan Junit4-
Johannes
1
Tautannya rusak. Adakah kemungkinan Anda dapat menemukan versi yang diarsipkan secara online atau meringkas isinya?
pzp
1

Menggunakan Hamcrest:

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

Ini juga berfungsi ketika set memiliki tipe data yang berbeda, dan melaporkan perbedaannya, bukan hanya gagal.

Hans-Peter Störr
sumber
2
Apa impor untuk isIn? IntelliJ tidak dapat menyelesaikan impor dengan paket hamcret apa pun.
fabien
0

Jika Anda ingin memeriksa apakah Daftar atau Kumpulan berisi sekumpulan nilai tertentu (alih-alih membandingkannya dengan koleksi yang sudah ada), seringkali metode koleksi toString berguna:

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

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

Ini sedikit lebih pendek daripada membuat koleksi yang diharapkan dan membandingkannya dengan koleksi sebenarnya, dan lebih mudah untuk menulis dan mengoreksi.

(Memang, ini bukan metode yang sangat bersih, dan tidak dapat membedakan elemen "foo, bar" dari dua elemen "foo" dan "bar". Namun dalam praktiknya, menurut saya yang paling penting adalah menulis tes yang mudah dan cepat , jika tidak, banyak pengembang tidak mau tanpa dipaksa.)

Hans-Peter Störr
sumber
Ini membuat hasil pengujian unit Anda bergantung pada implementasi toString dari daftar. Jika mereka memutuskan untuk mengubah format pengujian unit tidak akan berfungsi lagi. Saya tidak akan menganggap ini aman.
Laurens Op 't Zandt
@ LaurensOp'tZandt Maksud Anda Oracle mengubah format Collection.toList ()? Itu pasti tidak akan terjadi. Anda, bagaimanapun, benar itu tidak terlalu bersih. Tapi dalam praktiknya, kesan saya bahwa yang paling penting menulis tes itu sangat mudah.
Hans-Peter Störr
Saya setuju, saya pikir metode toString tidak akan mungkin terjadi. Jadi mungkin itu akan terus bekerja. Saya hanya ingin menunjukkan bahwa ini bukan cara yang sangat bersih. Tapi memang sangat mudah. Satu masalah yang muncul adalah saat membandingkan set. Karena pesanan mereka tidak dijamin.
Laurens Op 't Zandt
0

Saya suka solusi dari Hans-Peter Störr ... Tapi menurut saya itu tidak sepenuhnya benar. Sayangnya containsInAnyOrdertidak menerima Collectionkeberatan untuk dibandingkan. Jadi itu harus Collectiondari Matchers:

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

Impornya adalah:

import static java.util.stream.Collectors.toList;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertThat;
FLUXparticle
sumber