2013-11-25 9 views
18

Niedawno korzystałem z biblioteki Hamcrest, aby napisać kilka testów i całkiem udanych, ale teraz muszę zrobić coś bardziej złożonego i zacząłem dostrzegać wiele trudności. Muszę nanieść i zweryfikować właściwości przedmiotów na mapie. Mój kod produkcyjny wygląda mniej więcej tak:Jak używać Hamcrest do sprawdzania elementów mapy

Map<String, List<MyItem>> map = new HashMap<String, List<MyItem>>(); 
    map.put("one", Arrays.asList(new MyItem("One"))); 
    map.put("two", Arrays.asList(new MyItem("Two"))); 
    map.put("three", Arrays.asList(new MyItem("Three"))); 

Chcę napisać kilka kodów testowych, takich jak poniższe, ale nie kompiluje. Wygląda na to, że hasEntry Hamcresta jest sparametryzowane, podczas gdy hasItem i hasProperty oczekują tylko Object.

assertThat(map, Matchers.<String, List<MyItem>>hasEntry("one", hasItem(hasProperty("name", is("One"))))); 

Mój IDE (Eclipse) daje ten komunikat o błędzie: parametryczne metody <String, List<HamcrestTest.MyItem>>hasEntry(String, List<HamcrestTest.MyItem>) typu Matchers nie dotyczy argumentów (String, Matcher<Iterable<? super Object>>). Z jednej strony myślę, że Eclipse jest zdezorientowany z jakiej metody chciałem użyć, to powinien być hasEntry(org.hamcrest.Matcher<? super K> keyMatcher, org.hamcrest.Matcher<? super V> valueMatcher), a nie hasEntry(K key, V value).

Czy powinienem się poddać i pobrać przedmiot z mapy i ręcznie sprawdzić każdą nieruchomość? Czy istnieje czystszy sposób?

Odpowiedz

21

Youu może po prostu użyć contains lub containsInAnyOrder. To prawda, że ​​trzeba będzie wymienić wszystkie artykuły List ten sposób, ale działa czystsze niż hasItem:

@SuppressWarnings("unchecked") 
@Test 
public void mapTest() { 
    Map<String, List<MyItem>> map = new HashMap<String, List<MyItem>>(); 
    map.put("one", asList(new MyItem("1"), new MyItem("one"))); 

    assertThat(map, hasEntry(is("one"), 
          containsInAnyOrder(hasProperty("name", is("one")), 
               hasProperty("name", is("1"))))); 
} 
+1

nie wierzę, to będzie rozwiązać ten błąd kompilacji, ponieważ 'hasEntry' zwróci' Matcher > 'zamiast wymaganego' dopasowujący > ' –

+0

@JohnB: Wierz mi lub nie, ale spróbowałem i działa to dla mnie po prostu brzoskwiniowo. – t0mppa

+1

Może źle. Dobra decyzja. –

4

Więc po prostu zrobić to prościej można spróbować ...

assertThat((Object)map, (Matcher)Matchers.hasEntry("one", hasItem(hasProperty("name", is("One"))))); 

przechodząc do rodzaju surowca otrzymasz ostrzeżenie, ale nie błąd kompilacji. Jeśli używałeś tej sztuczki w przeszłości, gdy nie chcę martwić się o to, aby cały casting był odpowiedni dla kompilatora. Można również rozważyć użycie ItIterableContainingInOrder.containingInOrder(new MyItem("One"))). To sprawdzi całą listę i jeśli MyItem implementuje , to nie będziesz używał odbicia w twoich testach.

1

Ponieważ @ t0mppa nie stanowią dobry przykład jak używać Hamcrest na contains i containsInAnyOrder dla tego tutaj jest trochę coś, aby uzyskać swój początek:

Map<Integer, String> columns = new HashMap<Integer, String>(); 
columns.put(1, "ID"); 
columns.put(2, "Title"); 
columns.put(3, "Description"); 

assertThat(columns.values(), contains("ID", "Title", "Description")); // passes 
assertThat(columns.values(), contains("ID", "Description", "Title")); // fails 
assertThat(columns.values(), containsInAnyOrder("ID", "Description", "Title")); // passes 

należy zauważyć, że w przeciwieństwie do hasItem i hasItems, to będzie działać tylko wtedy, gdy zapewni im pełną listę wszystkich wartości będziesz pasującymi przeciw. Zobacz Hamcrest's javadocs, aby uzyskać więcej informacji.

Powiązane problemy