Hamcrest koleksiyonları karşılaştır


114

2 listeyi karşılaştırmaya çalışıyorum:

assertThat(actual.getList(), is(Matchers.containsInAnyOrder(expectedList)));

Ama fikir

java: no suitable method found for assertThat(java.util.List<Agent>,org.hamcrest.Matcher<java.lang.Iterable<? extends model.Agents>>)
method org.junit.Assert.<T>assertThat(T,org.hamcrest.Matcher<T>) is not applicable
  (no instance(s) of type variable(s) T exist so that argument type org.hamcrest.Matcher<java.lang.Iterable<? extends model.Agents>> conforms to formal parameter type org.hamcrest.Matcher<T>)
method org.junit.Assert.<T>assertThat(java.lang.String,T,org.hamcrest.Matcher<T>) is not applicable
  (cannot instantiate from arguments because actual and formal argument lists differ in length)

Nasıl yazmalıyım?

Yanıtlar:


161

İki listenin aynı olduğunu iddia etmek istiyorsanız, Hamcrest ile işleri karıştırmayın:

assertEquals(expectedList, actual.getList());

Gerçekten sıraya duyarlı olmayan bir karşılaştırma containsInAnyOrderyapmayı düşünüyorsanız , varargs yöntemini çağırabilir ve değerleri doğrudan sağlayabilirsiniz:

assertThat(actual.getList(), containsInAnyOrder("item1", "item2"));

(Listenizin String, yerineAgent bu örnekten .)

Aynı yöntemi gerçekten a içeriğiyle çağırmak istiyorsanız List:

assertThat(actual.getList(), containsInAnyOrder(expectedList.toArray(new String[expectedList.size()]));

Bu olmadan, yöntemi tek bir bağımsız değişkenle çağırırsınız ve her öğenin a olduğu Matcherbir Iterableyerde eşleşmeyi bekleyen bir . Bu bir eşleştirmek için kullanılamazListList .

Yani, a List<Agent>ile a'yı eşleştiremezsiniz Matcher<Iterable<List<Agent>>, bu kodunuzun çalıştığı şeydir.


"Aynı yöntemi bir Listenin içeriğiyle gerçekten çağırmak istiyorsanız" için +1. Ne yazık ki bunu kendim çözemedim. Özellikle bir koleksiyon alan bir kurucu var.
Eyad Ebrahim

3
@Tim Pek değil; tüm öğelerin mevcut containsInAnyOrderolmasını gerektirir , böylece ilk iddia başarısız olur. En azından bu öğelerin mevcut olup olmadığını kontrol etmek isteyip istemediğinize bakın . hasItems
Joe

4
Eğer containsInAnyOrder kullanırsanız, önce emin iki liste de aynı boyutta yapmalıdır ... Eğer actual.getList()barındırıyorsa bu "item1", "item3", "item2"test geçecek ve belki emin olmak istiyorum sadece listelenen öğeleri içerir ... Bu durumda kullanabilirsiniz assertThat(actual.getList().size(), equalTo(2));containsInAnyOrder'dan önce, bu şekilde her iki listenin de aynı içeriğe sahip olduğundan emin olursunuz.
Martin

1
@Martin düşünüyorsun hasItems. Ekstra kontrol burada gereksizdir. Yukarıdaki Tim yorumuna bakın ve ayrıca Hamcrest'in hasItems, içerir ve içerirInAnyOrder nasıl farklılık gösterir?
Joe

1
Kotlin kullanıcıları : *expectedList.toTypedArray()Bir diziyi varargs olarak iletirken spread operatörünü ( ) eklemeyi unutmayın !
James Bowman

63
List<Long> actual = Arrays.asList(1L, 2L);
List<Long> expected = Arrays.asList(2L, 1L);
assertThat(actual, containsInAnyOrder(expected.toArray()));

Gereksiz parametreler olmadan @ Joe'nun yanıtının daha kısa versiyonu.


28

@ Joe'nun cevabını tamamlamak için:

Hamcrest, bir listeyi eşleştirmek için size üç ana yöntem sunar:

contains Sırayı sayan tüm öğeleri eşleştirmeyi denetler, listede daha fazla veya daha az öğe varsa, başarısız olur

containsInAnyOrder Tüm öğelerin eşleşip eşleşmediğini denetler ve sıra önemli değildir, listede daha fazla veya daha az öğe varsa başarısız olur

hasItems Listenin daha fazlasına sahip olup olmadığı önemli değildir, sadece belirtilen nesneleri kontrol eder

hasItem Listede daha fazla nesne olup olmadığı önemli değil sadece bir nesneyi kontrol eder

Hepsi bir nesne listesi alabilir ve equalskarşılaştırma için yöntem kullanabilir veya @ borjab gibi diğer eşleştiricilerle karıştırılabilir:

assertThat(myList , contains(allOf(hasProperty("id", is(7L)), 
                                   hasProperty("name", is("testName1")),
                                   hasProperty("description", is("testDesc1"))),
                             allOf(hasProperty("id", is(11L)), 
                                   hasProperty("name", is("testName2")),
                                   hasProperty("description", is("testDesc2")))));

http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matchers.html#contains (E ...) http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matchers.html #containsInAnyOrder (java.util.Collection) http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matchers.html#hasItems (T ...)


Partiye biraz geç, ancak her yöntem arasındaki farkların açıklaması için teşekkürler.
Marcos de Andrade

Liste öğelerinin ilkel türde olmaması durumunda harika bir karar.
Stanislav Tsepa

Bunu yapmanın güvenli bir yolu var mı?
andresp

15

Mevcut Hamcrest kitaplıklarıyla (v.2.0.0.0'dan itibaren), containsInAnyOrder Eşleştiricisini kullanmak için Koleksiyonunuzda Collection.toArray () yöntemini kullanmak zorunda kalırsınız. Bunu org.hamcrest.Matchers'a ayrı bir yöntem olarak eklemek çok daha güzel olurdu:

public static <T> org.hamcrest.Matcher<java.lang.Iterable<? extends T>> containsInAnyOrder(Collection<T> items) {
    return org.hamcrest.collection.IsIterableContainingInAnyOrder.<T>containsInAnyOrder((T[]) items.toArray());
}

Aslında bu yöntemi özel test kitaplığıma ekledim ve test durumlarımın okunabilirliğini artırmak için kullandım (daha az ayrıntı nedeniyle).


2
Güzel olan, bu yardımcıyı kullanacağım. Buradaki iddia mesajı daha bilgilendirici: eksik öğeleri tek tek adlandırıyor, sadece: liste elem1, elem2, .. elem99 olmalı, ama elem1, elem2, ..., elem98 - bol şanslar eksik olanı bulmak.
pihentagy

3

ObjectListenizdeki e-postaların üzerlerinde equals()tanımlandığından emin olun . Sonra

    assertThat(generatedList,is(equalTo(expectedList)));

İşler.


1

Nesnelerin listesi için şunun gibi bir şeye ihtiyacınız olabilir:

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;
import static org.hamcrest.Matchers.is;

@Test
@SuppressWarnings("unchecked")
public void test_returnsList(){

    arrange();
  
    List<MyBean> myList = act();
    
    assertThat(myList , contains(allOf(hasProperty("id",          is(7L)), 
                                       hasProperty("name",        is("testName1")),
                                       hasProperty("description", is("testDesc1"))),
                                 allOf(hasProperty("id",          is(11L)), 
                                       hasProperty("name",        is("testName2")),
                                       hasProperty("description", is("testDesc2")))));
}

Nesnelerin sırasını kontrol etmek istemiyorsanız, containsInAnyOrder'ı kullanın .

Not: Bastırılan uyarıyı önlemeye yönelik herhangi bir yardım gerçekten takdir edilecektir.


-3

İki listeyi kullanım sırasına göre karşılaştırmak için,

assertThat(actualList, contains("item1","item2"));

Bu soruya cevap vermiyor.
kamczak

Kısmen yapar.
rvazquezglez

@rvazquezglez Ne demek istiyorsun? Neden öyle diyorsun? Yöntemin sonucu benim çevremde doğru.
niaomingjian

@niaomingjian Kod, eşleştiricinin actualListiçindeki öğeleri içerip içermediğini kontrol ediyor, öğeler containsaynı sırada değilse başarısız olur ve daha fazla öğe içeriyorsa veya eksikse başarısız olur.
rvazquezglez

@rvazquezglez yani kodun amacı tam eşitliği (aynı uzunluklar, değerler ve sıra) iki listede incelemek, değil mi?
niaomingjian
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.