2010-07-13 11 views
101

Come fare asserzioni su un elenco in un JUnit test case? Non solo la dimensione della lista ma anche i contenuti della lista.Assert su un elenco in Junit

+0

Mi piace utilizzare 'assertArrayEquals' al giorno d'oggi. Utilizzare in combinazione con 'Lista # perArray'. – Thibstars

risposta

18

Questa è una risposta legacy, adatta per JUnit 4.3 e versioni successive. La versione moderna di JUnit include un messaggio di errore leggibile incorporato nel metodo assertThat. Preferisci altre risposte a questa domanda, se possibile.

List<E> a = resultFromTest(); 
List<E> expected = Arrays.asList(new E(), new E(), ...); 
assertTrue("Expected 'a' and 'expected' to be equal."+ 
      "\n 'a'  = "+a+ 
      "\n 'expected' = "+expected, 
      expected.equals(a)); 

Per la cronaca, come @ Paolo citato nel suo commento a questa risposta, due List s sono uguali:

se e solo se l'oggetto specificato è anche una lista, entrambe le liste hanno la stessa dimensione e tutte le corrispondenti coppie di elementi nei due elenchi sono uguali. (Due elementi e1 e e2 sono uguali se (e1==null ? e2==null : e1.equals(e2)).) In altre parole, due liste sono definite uguali se contengono gli stessi elementi nello stesso ordine. Questa definizione garantisce che il metodo equals funzioni correttamente attraverso diverse implementazioni dell'interfaccia List.

Vedere JavaDocs of the List interface.

+1

Quindi vuoi dire expected.equals (a) si prenderà cura di affermare gli oggetti che la lista sta tenendo? – Kamal

+1

Da elenco javadoc: confronta l'oggetto specificato con questo elenco per l'uguaglianza. Restituisce true se e solo se l'oggetto specificato è anche un elenco, entrambi gli elenchi hanno la stessa dimensione e tutte le corrispondenti coppie di elementi nei due elenchi sono uguali. (Due elementi e1 ed e2 sono uguali se (e1 == null? E2 == null: e1.equals (e2)).) In altre parole, due liste sono definite uguali se contengono gli stessi elementi nello stesso ordine . Questa definizione garantisce che il metodo equals funzioni correttamente attraverso diverse implementazioni dell'interfaccia List. –

+0

@Kamal, sì (vedere il commento di Paolo e la mia modifica). –

104

Mi rendo conto che questo è stato chiesto un paio di anni fa, probabilmente questa funzione non era ancora disponibile. Ma adesso, è facile da fare proprio questo:

@Test 
public void test_array_pass() 
{ 
    List<String> actual = Arrays.asList("fee", "fi", "foe"); 
    List<String> expected = Arrays.asList("fee", "fi", "foe"); 

    assertThat(actual, is(expected)); 
    assertThat(actual, is(not(expected))); 
} 

Se si dispone di una versione recente di Junit installato con hamcrest, basta aggiungere queste importazioni:

import static org.junit.Assert.*; 
import static org.hamcrest.CoreMatchers.*; 

http://junit.org/junit4/javadoc/latest/org/junit/Assert.html#assertThat(T, org.hamcrest.Matcher)

http://junit.org/junit4/javadoc/latest/org/hamcrest/CoreMatchers.html

http://junit.org/junit4/javadoc/latest/org/hamcrest/core/Is.html

+1

@ djeikyb- sembra una buona caratteristica. Grazie per l'aggiornamento. – Kamal

+2

'System.out.println (actual == expected);' restituirà false, ma 'System.out.println (actual.equals (expected));' restituirà true. – Catfish

+0

@Catfish sì, questo è confuso, non è vero? Penso che stavo dimostrando che il matcher sta usando '.equals (..)' invece di '=='? – djeikyb

7

Se lo si fa non mi interessa l'ordine degli elementi, raccomando ListAssert.assertEquals in addon di junit.

Link: http://junit-addons.sourceforge.net/

Per gli utenti di Maven pigri:

<dependency> 
     <groupId>junit-addons</groupId> 
     <artifactId>junit-addons</artifactId> 
     <version>1.4</version> 
     <scope>test</scope> 
    </dependency> 
+6

Nota: se non ti interessa l'ordine degli elementi, dovresti utilizzare un set o una raccolta, non una lista. – Barett

+9

Sono d'accordo. Questa libreria è lesa. Perché mai ListAssert.assertEquals() dovrebbe essere impostato su ordine? – Ryan

0

Non reinventare la ruota!

C'è una libreria di Google Code che fa questo per voi: Hamcrest

[Hamcrest] fornisce una libreria di oggetti matcher (noto anche come vincoli o predicati) permettendo regole 'match' da definire in modo dichiarativo, a essere utilizzato in altri framework. Gli scenari tipici includono framework di test, librerie di simulazione e regole di convalida dell'interfaccia utente.

0

se non si vuole costruire una lista di array, si può provare questo anche

@Test 
public void test_array_pass() 
{ 
    List<String> list = Arrays.asList("fee", "fi", "foe"); 
    Strint listToString = list.toString(); 
    Assert.assertTrue(listToString.contains("[fee, fi, foe]")); // passes 
} 
14

Non trasformare a stringa e confrontare.Questo non va bene per la perfomance. Nel JUnit, all'interno Corematchers, c'è un matcher per questo =>hasItems

List<Integer> yourList = Arrays.asList(1,2,3,4)  
assertThat(yourList, CoreMatchers.hasItems(1,2,3,4,5)); 

Questo è il modo migliore che io conosca per controllare elementi di una lista.

+1

Dovrebbe essere la risposta scelta, con una nota: è necessario anche verificare che non ci siano più elementi nella lista oltre a ciò che si desidera. Forse usare: 'Assert.assertEquals (4, yourList.size());' – yoni

+0

o con una sola riga: 'assertThat (yourList.toArray(), arrayContainingInAnyOrder (1,2,3,4,5));' – user1778602

3
List<Integer> figureTypes = new ArrayList<Integer>(
          Arrays.asList(
           1, 
           2 
          )); 

List<Integer> figureTypes2 = new ArrayList<Integer>(
          Arrays.asList(
           1, 
           2)); 

assertTrue(figureTypes .equals(figureTypes2)); 
0

Non so che tutte le risposte di cui sopra stanno dando la soluzione esatta per il confronto di due elenchi di oggetti. La maggior parte degli approcci di cui sopra può essere utile nel seguire limite di confronti solo - Confronto di formato - confronto di riferimento

Ma se dobbiamo stessi elenchi di dimensioni di oggetti e dati diversi sugli oggetti livello allora si avvicina a questo confronto non aiuterà .

Penso che il seguente approccio funzionerà perfettamente con l'override equals e il metodo hashcode sull'oggetto definito dall'utente.

Ho usato Xstream lib per l'override uguale e l'hashcode, ma possiamo anche ignorare equals e hashcode per logiche/confronti vinti.

Ecco l'esempio per il vostro riferimento

import com.thoughtworks.xstream.XStream; 

    import java.text.ParseException; 
    import java.util.ArrayList; 
    import java.util.List; 

    class TestClass { 
     private String name; 
     private String id; 

     public void setName(String value) { 
     this.name = value; 
     } 

     public String getName() { 
     return this.name; 
     } 

     public String getId() { 
     return id; 
     } 

     public void setId(String id) { 
     this.id = id; 
     } 

     /** 
     * @see java.lang.Object#equals(java.lang.Object) 
     */ 
     @Override 
     public boolean equals(Object o) { 
     XStream xstream = new XStream(); 
     String oxml = xstream.toXML(o); 
     String myxml = xstream.toXML(this); 

     return myxml.equals(oxml); 
     } 

     /** 
     * @see java.lang.Object#hashCode() 
     */ 
     @Override 
     public int hashCode() { 
     XStream xstream = new XStream(); 
     String myxml = xstream.toXML(this); 
     return myxml.hashCode(); 
     } 
    } 

    public class XstreamCompareTest { 
     public static void main(String[] args) throws ParseException { 
     checkObjectEquals(); 
} 

     private static void checkObjectEquals() { 
     List<TestClass> testList1 = new ArrayList<TestClass>(); 
     TestClass tObj1 = new TestClass(); 
     tObj1.setId("test3"); 
     tObj1.setName("testname3"); 
     testList1.add(tObj1); 

     TestClass tObj2 = new TestClass(); 
     tObj2.setId("test2"); 
     tObj2.setName("testname2"); 
     testList1.add(tObj2); 

     testList1.sort((TestClass t1, TestClass t2) -> t1.getId().compareTo(t2.getId())); 

     List<TestClass> testList2 = new ArrayList<TestClass>(); 
     TestClass tObj3 = new TestClass(); 
     tObj3.setId("test3"); 
     tObj3.setName("testname3"); 
     testList2.add(tObj3); 

     TestClass tObj4 = new TestClass(); 
     tObj4.setId("test2"); 
     tObj4.setName("testname2"); 
     testList2.add(tObj4); 

     testList2.sort((TestClass t1, TestClass t2) -> t1.getId().compareTo(t2.getId())); 

     if (isNotMatch(testList1, testList2)) { 
      System.out.println("The list are not matched"); 
     } else { 
      System.out.println("The list are matched"); 
     } 

     } 

     private static boolean isNotMatch(List<TestClass> clist1, List<TestClass> clist2) { 
     return clist1.size() != clist2.size() || !clist1.equals(clist2); 
     } 
    } 

La cosa più importante è che si può ignorare i campi di annotazione (@XStreamOmitField) se non si desidera includere tutti i campi sulla parità di controllo Oggetti. Ci sono molte annotazioni come questa da configurare, quindi dai un'occhiata in profondità alle annotazioni di questa lib.

Sono certo che questa risposta farà risparmiare tempo per identificare l'approccio corretto per il confronto di due elenchi di oggetti :). Si prega di commentare se vedete eventuali problemi su questo.