JUnit 4 confronta i set


102

Come affermeresti succintamente l'uguaglianza degli Collectionelementi, in particolare a Setin JUnit 4?



Stai cercando di affermare che due Set sono uguali tra loro (contengono gli stessi elementi) o che due elementi dello stesso Set sono uguali?
Bill the Lizard

Devo vedere che gli elementi di due set sono uguali
Eqbal

Risposte:


103

Puoi affermare che le due Sets sono uguali tra loro, il che richiama il Set equals()metodo .

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

Questo @Testpasserà se i due Sethanno la stessa dimensione e contengono gli stessi elementi.


7
Ciò non mostra risultati molto buoni nel rapporto. Se le tue toStrings sono chiaramente definite è meglio, ma comunque non va bene (una piccola differenza può finire con una pagina di testo)
Bill K

Uhm, come mai ottengo: java.lang.AssertionError: previsto: java.util.Hashtable <{CompanyName = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Category = AvrIfd, QuoteIfd, QuoteId = 4342740212049 = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Category = AvrIfd, QuoteId = 4342740204922826921}>
Giovanni Botta

3
@Giodude Hai equalse hashCodeimplementato nella classe che stai memorizzando nel tuo Hashtable?
Bill the Lizard

Come puoi vedere quelle sono solo stringhe e un lungo ... Sto testando Avro per serializzare e deserializzare una mappa e questo è il risultato. Penso che ci debba essere qualcosa di strano nel modo in cui le stringhe sono serializzate e deserializzate che fa fallire il test, ma non riesco a trovare il problema.
Giovanni Botta

Non ha funzionato per me anche se sto confrontando due HashSet <Long>. La risposta di @ MattFriedman funziona effettivamente per il mio caso d'uso.
bluecollarcoder

46

Apache comunica di nuovo in soccorso.

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

Funziona come un fascino. Non so perché, ma ho scoperto che con le collezioni assertEquals(coll1, coll2)ciò che segue non sempre funziona. Nel caso in cui non fosse riuscito per me, avevo due raccolte supportate da Sets. Né hamcrest né junit direbbero che le collezioni erano uguali anche se sapevo per certo che lo erano. Utilizzando CollectionUtils funziona perfettamente.


20
Questo in realtà è banale, la parte difficile è indicare chiaramente la differenza al chiamante
Bill K

1
La risposta accettata è una buona risposta per la domanda originale (test unitario specifico per due set) ma questa risposta con CollectionUtils credo sia una risposta migliore per il caso più generale. Non ero in grado di confrontare una raccolta e un set se non utilizzando CollectionUtils.
Jay

16

con hamcrest :

assertThat(s1, is(s2));

con semplice affermazione:

assertEquals(s1, s2);

NB: t viene utilizzato il metodo equals () della classe concrete set


1
Preferisco questo metodo poiché Hamcrest viene fornito con JUnit 4, quindi non c'è bisogno di altre librerie.
JRS del

2
Questo potrebbe non funzionare quando i set hanno tipi diversi.
Hans-Peter Störr

7

Un caso particolarmente interessante è quando si confronta

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

e

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

Finora, l'unica soluzione che vedo è cambiarli entrambi in set

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

Oppure potrei confrontarli elemento per elemento.


In realtà, ci sono diverse soluzioni per quello presentato nelle altre risposte. I set sono un po 'sfortunati per questo, comunque, poiché ignorano l'ordine. Forse ArrayList?
Hans-Peter Störr

4

Come metodo aggiuntivo basato su array ... puoi prendere in considerazione l'utilizzo di asserzioni di array non ordinate in junitx. Anche se l'esempio di Apache CollectionUtils funzionerà, c'è anche un pacchetto di solide estensioni di asserzioni:

Penso che il file

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

sarà molto più leggibile e debuggabile per te (tutte le raccolte supportano toArray (), quindi dovrebbe essere abbastanza facile usare i metodi ArrayAssert.

Ovviamente lo svantaggio qui è che junitx è un file jar aggiuntivo o una voce Maven ...

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

2

Controlla questo articolo . Un esempio da lì:

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

Link breve ma fantastico, spiega molto velocemente cosa puoi fare con Junit4-
Johannes

1
Il collegamento è interrotto. Hai qualche possibilità di trovare online una versione archiviata o di riassumerne il contenuto?
pzp

1

Utilizzando Hamcrest:

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

Questo funziona anche quando i set hanno diversi tipi di dati e segnala la differenza invece di fallire.


2
Qual è l'importazione per isIn? IntelliJ non può risolvere l'importazione con nessun pacchetto hamcret.
fabien

0

Se vuoi controllare se un elenco o un insieme contiene un insieme di valori specifici (invece di confrontarlo con una raccolta già esistente), spesso il metodo delle raccolte toString è utile:

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

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

Questo è un po 'più breve rispetto alla prima costruzione della raccolta prevista e al confronto con la raccolta effettiva, e più facile da scrivere e correggere.

(Certo, questo non è un metodo particolarmente pulito, e non può distinguere un elemento "foo, bar" da due elementi "foo" e "bar". Ma in pratica penso che sia più importante che sia facile e veloce scrivere test , altrimenti molti sviluppatori non lo faranno senza essere pressati.)


Questo fa sì che il risultato del tuo unit test dipenda dall'implementazione di toString from list. Se decidono di cambiare la formattazione lo unit test non funzionerà più. Non lo considererei sicuro.
Laurens Op 't Zandt

@ LaurensOp'tZandt Vuoi dire che Oracle sta cambiando il formato di Collection.toList ()? Certamente non succederà. Hai comunque ragione che non è particolarmente pulito. Ma in pratica, ho l'impressione che sia molto importante che sia molto facile scrivere test.
Hans-Peter Störr

Sono d'accordo, penso che il metodo toString non sarà probabilmente casuale. Quindi probabilmente continuerà a funzionare. Volevo solo sottolineare che non è un modo molto pulito. Ma in effetti è molto facile. Un problema che sorge è quando si confrontano gli insiemi. Poiché il loro ordine non è garantito.
Laurens Op 't Zandt

0

Mi piace la soluzione di Hans-Peter Störr ... Ma penso che non sia del tutto corretta. Purtroppo containsInAnyOrdernon accetta un Collectiondi oggetti da confrontare. Quindi deve essere un Collectiondi Matchers:

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

Le importazioni sono:

import static java.util.stream.Collectors.toList;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertThat;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.