2012-08-28 14 views
70

Si supponga che voglio unit test un metodo con questa firma:Come posso affermare che Iterable contenga elementi con una certa proprietà?

List<MyItem> getMyItems(); 

supponga MyItem è un POJO che ha molte proprietà, uno dei quali è "name", accessibile tramite getName().

Tutto mi interessa verificare è che il List<MyItem>, o qualsiasi Iterable, contiene due MyItem casi, le cui proprietà "name" hanno i valori "foo" e "bar". Se altre proprietà non corrispondono, non mi interessa per gli scopi di questo test. Se i nomi corrispondono, è un test riuscito.

Mi piacerebbe che fosse un liner, se possibile. Ecco alcune "pseudo-sintassi" del tipo di cosa che vorrei fare.

assert(listEntriesMatchInAnyOrder(myClass.getMyItems(), property("name"), new String[]{"foo", "bar"}); 

Hamcrest sarebbe buono per questo tipo di cose? In tal caso, quale sarebbe esattamente la versione hamcrest della mia pseudo-sintassi sopra?

risposta

76

Grazie @Razvan che mi ha indirizzato nella giusta direzione. Sono riuscito a metterlo in una riga e ho rintracciato con successo le importazioni per Hamcrest 1.3.

le importazioni:

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

il codice:

assertThat(myClass.getMyItems(), contains(
    hasProperty("name", is("foo")), 
    hasProperty("name", is("bar")) 
)); 
38

Prova:

assertThat(myClass.getMyItems(), 
          hasItem(hasProperty("YourProperty", is("YourValue")))); 
+1

proprio come un nodo laterale - questa è una soluzione hamcrest (non assertj) – Hartmut

3

Finché il tuo List è una classe concreta, si può semplicemente chiamare il metodo contains() fintanto che è stato implementato il tuo equals() metodo su MyItem.

// given 
// some input ... you to complete 

// when 
List<MyItems> results = service.getMyItems(); 

// then 
assertTrue(results.contains(new MyItem("foo"))); 
assertTrue(results.contains(new MyItem("bar"))); 

Si presuppone che sia stato implementato un costruttore che accetta i valori su cui si desidera far valere. Mi rendo conto che questo non è su una singola riga, ma è utile sapere quale valore manca, piuttosto che controllarlo entrambi contemporaneamente.

+0

Mi piace molto la tua soluzione, ma dovresti mod tutto quel codice per un test? –

+0

Immagino che ogni risposta qui richiederà alcune impostazioni di test, l'esecuzione del metodo da testare e quindi l'affermazione delle proprietà. Non c'è un reale sovraccarico della mia risposta da ciò che posso vedere, solo che ho due affermazioni sulle linee del seaprate in modo che un'asserzione fallita possa identificare chiaramente quale valore manca. – Brad

+0

Sarebbe meglio includere anche un messaggio all'interno di assertTrue in modo che il messaggio di errore sia più comprensibile. Senza un messaggio, se fallisce, JUnit lancia semplicemente un AssertionFailedError senza alcun messaggio di errore. Quindi è meglio includere qualcosa come "i risultati dovrebbero contenere nuovo MyItem (\" pippo \ ")". – Max

21

La sua non è particolarmente Hamcrest, ma penso che ne vale la pena menzionare qui. Quello che uso molto spesso in Java8 è qualcosa di simile:

assertTrue(myClass.getMyItems().stream().anyMatch(item -> "foo".equals(item.getName()))); 

(... A cura di lieve miglioramento di Rodrigo Manyari E 'un po' meno prolissa Vedere i commenti)

Può essere un po 'più difficile da leggi, ma mi piace il tipo e la sicurezza del refactoring. È anche bello per testare più proprietà del bean in combinazione. per esempio. con un'espressione java-like & & nel filtro lambda.

+2

Leggero miglioramento: assertTrue (myClass.getMyItems(). Stream(). AnyMatch (item -> "foo" .equals (item.getName ())); –

+0

@RodrigoManyari, parentesi chiusa mancante – Abdull

15

Assertj è buono a questo.

import static org.assertj.core.api.Assertions.assertThat; 

    assertThat(myClass.getMyItems()).extracting("name").contains("foo", "bar"); 

Un grande vantaggio per assertj rispetto a hamcrest è un facile utilizzo del completamento del codice.

Problemi correlati