JUnit 4 Karşılaştırma Setleri


103

CollectionElemanların eşitliğini , özellikle Setde JUnit 4'te özlü bir şekilde nasıl iddia edersiniz ?


2
bu SO gönderisine göz
atın

İki Setin birbirine eşit olduğunu (aynı öğeleri içerdiğini) veya aynı Setin iki öğesinin eşit olduğunu mu iddia ediyorsunuz?
Bill the Lizard

İki
Setin

Yanıtlar:


104

İki Sets'nin birbirine eşit olduğunu iddia edebilirsiniz , bu da Set equals()yöntemi çağırır .

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

Bu @Testiki halinde geçecek Setler aynı boyutta ve aynı elemanları içermektedir.


7
Bu raporda çok iyi sonuçlar göstermiyor. Eğer toString'leriniz açıkça tanımlanmışsa, daha iyidir, ancak yine de iyi değildir (Küçük bir fark, bir sayfa metinle sonuçlanabilir)
Bill K,

Uhm, nasıl oluyor da java.lang.AssertionError: beklenen: java.util.Hashtable <{CompanyName = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Category = AvrIfd, Quoteable = 434274020492 = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Category = AvrIfd, QuoteId = 4342740204922826921}>
Giovanni Botta

3
@Giodude Hashtable'ınızda sakladığınız sınıfta var equalsve uyguluyor musunuz hashCode?
Bill the Lizard

Gördüğünüz gibi bunlar sadece dizeler ve uzun ... Avro'yu bir haritayı serileştirmek ve serileştirmek için test ediyorum ve sonuç bu. Sanırım dizelerin serileştirilmesi ve serileştirilmesinden çıkarılmasıyla ilgili olarak testin başarısız olmasına neden olan şüpheli bir şeyler olmalı, ancak sorunu bulamıyorum.
Giovanni Botta

İki HashSet <Long> 'u karşılaştırmama rağmen benim için işe yaramadı. @MattFriedman cevabı aslında benim kullanım durumum için çalışıyor.
bluecollarcoder

46

Apache kurtarmaya tekrar ortak olur.

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

Tıkır tıkır çalışıyor. Nedenini bilmiyorum ama koleksiyonlarda aşağıdakilerin assertEquals(coll1, coll2)her zaman işe yaramadığını buldum . Benim için başarısız olması durumunda, Sets tarafından desteklenen iki koleksiyonum vardı. Ne hamcrest ne de junit, emin olduğumdan emin olmama rağmen koleksiyonların eşit olduğunu söylemezdi. CollectionUtils'i kullanmak mükemmel çalışıyor.


20
Bu aslında önemsiz, işin zor kısmı arayanla aradaki farkı açıkça belirtmek
Bill K

1
Kabul edilen cevap, orijinal soru için iyi bir cevaptır (özellikle iki Set için birim testi), ancak CollectionUtils ile verilen bu cevap, bence en genel durum için daha iyi bir cevaptır. CollectionUtils'i kullanmadan bir Koleksiyonu ve Seti karşılaştıramadım.
Jay

16

ile hamcrest :

assertThat(s1, is(s2));

düz iddia ile:

assertEquals(s1, s2);

NB: t beton set sınıfının equals () yöntemi kullanılır


1
Hamcrest JUnit 4 ile birlikte geldiği için bu yöntemi tercih ediyorum, bu yüzden diğer kitaplıklara gerek yok.
JRSofty

2
Setlerin farklı türleri olduğunda bu işe yaramayabilir.
Hans-Peter Störr

7

Özellikle ilginç bir durum,

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

ve

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

Şimdiye kadar gördüğüm tek çözüm, ikisini de setlere dönüştürmek.

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

Ya da onları öğe öğe karşılaştırabilirim.


Aslında, diğer cevaplarda sunulan bunun için birkaç çözüm var. Setler, sıralamayı görmezden geldikleri için bunun için biraz talihsizdir. Belki ArrayList?
Hans-Peter Störr

4

Dizi tabanlı ek bir yöntem olarak ... sırasız dizi iddialarını junitx'te kullanmayı düşünebilirsiniz. Apache CollectionUtils örneği işe yarayacak olsa da, orada da bir dizi katı iddia uzantısı var:

Bence

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

yaklaşımı sizin için çok daha okunabilir ve hata ayıklanabilir olacaktır (tüm Koleksiyonlar toArray () 'ı destekler, bu nedenle ArrayAssert yöntemlerini kullanmak yeterince kolay olmalıdır.

Tabii ki buradaki dezavantajı, junitx'in ek bir jar dosyası veya maven girişi olmasıdır ...

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

2

Kontrol bu yazıyı . Oradan bir örnek:

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

kısa ama harika Link, Junit4 ile neler yapabileceğinizi gerçekten hızlı açıklıyor
Johannes

1
Bağlantı koptu. Arşivlenmiş bir sürümü çevrimiçi olarak bulma veya içeriğini özetleme şansınız var mı?
pzp

1

Hamcrest Kullanımı:

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

Bu, kümeler farklı veri türlerine sahip olduğunda da çalışır ve yalnızca başarısız olmak yerine farkı rapor eder.


2
İsIn için içe aktarım nedir? IntelliJ, herhangi bir hamcret paketiyle içe aktarmayı çözemez.
fabien

0

Bir Liste veya Kümenin belirli bir değer kümesi içerip içermediğini kontrol etmek istiyorsanız (zaten var olan bir koleksiyonla karşılaştırmak yerine), genellikle toString koleksiyon yöntemi kullanışlıdır:

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

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

Bu, beklenen koleksiyonu ilk oluşturup onu gerçek koleksiyonla karşılaştırmaktan biraz daha kısadır ve yazmak ve düzeltmek daha kolaydır.

(Kuşkusuz, bu özellikle temiz bir yöntem değildir ve "foo, bar" öğesini iki öğeden "foo" ve "bar" dan ayırt edemez. Ancak pratikte testleri yazmanın kolay ve hızlı olması bence çok önemlidir , aksi takdirde birçok geliştirici basılmadan yapmaz.)


Bu, birim testinizin sonucunun listeden toString uygulamasına bağlı olmasını sağlar. Biçimlendirmeyi değiştirmeye karar verirlerse, birim testi artık çalışmayacaktır. Bunu güvenli saymazdım.
Laurens Op 't Zandt

@ LaurensOp'tZandt Oracle'ın Collection.toList () biçimini değiştirmesini mi kastediyorsunuz? Bu kesinlikle olmayacak. Bununla birlikte, haklısınız, bu özellikle temiz değil. Ama pratikte, test yazmanın çok kolay olması benim izlenimim.
Hans-Peter Störr

Katılıyorum, toString yönteminin şansa bağlı olmayacağını düşünüyorum. Yani muhtemelen çalışmaya devam edecek. Sadece bunun çok temiz bir yol olmadığını belirtmek istedim. Ama gerçekten çok kolay. Ortaya çıkan sorunlardan biri, kümeleri karşılaştırırken ortaya çıkar. Siparişleri garanti edilmediğinden.
Laurens Op 't Zandt

0

Hans-Peter Störr'ün çözümünü beğendim ... Ama bence bu pek doğru değil. Ne yazık ki containsInAnyOrder, Collectionkarşılaştırmak için nesnelerden birini kabul etmiyor . Bu yüzden bir olmak zorunda Collectionarasında Matchers:

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

İthalat:

import static java.util.stream.Collectors.toList;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertThat;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.