2009-07-07 6 views
54

Perché questo non compila, oh, cosa fare?Perché questo codice che tenta di utilizzare hasItem di Hamcrest non viene compilato?

import static org.junit.Assert.assertThat; 
import static org.junit.matchers.JUnitMatchers.hasItems; 

ArrayList<Integer> actual = new ArrayList<Integer>(); 
ArrayList<Integer> expected = new ArrayList<Integer>(); 
actual.add(1); 
expected.add(2); 
assertThat(actual, hasItems(expected)); 

errore copiato da un commento:

cannot find symbol method assertThat(java.util.ArrayList<java.lang.Integer>, org.hamcreset.Matcher<java.lang.Iterable<java.util.ArrayList<java.lang.Integer>>>) 

risposta

12

si sta confrontando con ArrayList<Integer>int. Il confronto corretto è:

... 
assertThat(actual, hasItem(2)); 

- Modifica -

Mi dispiace, ho letto male. In ogni caso, la firma di hasItems che si desidera è:

public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItems(T... elements) 

vale a dire, si accetta un numero variabile di argomenti. Non sono sicuro che un ArrayList<T> sia compatibile, solo indovinando qui. Prova a inviare ogni elemento dall'elenco previsto intervallato dalla virgola.

assertThat(actual, hasItems(2,4,1,5,6)); 

- Modifica 2 -

Basta incollare qui il mio commento, c'è un'espressione equivalente per ciò che si vuole, senza usare Hamcrest:

assertTrue(actual.containsAll(expected)); 
+0

sto paragonando più elementi. (hasItems, non hasItem) – ripper234

+0

Quindi, hamcrest semplicemente non supporta il confronto di due raccolte? (Non ho un elenco effettivo di elementi, sto costruendo l'elenco di numeri da 0 a 999 Devo confrontare le collezioni). – ripper234

+0

Non posso rispondere per questo, lo dico sulla base della documentazione. Ma c'è un modo più semplice per fare ciò che vuoi ... usa assertTrue (actual.containsAll (expected)). – freitass

2

Questo messaggio di errore sembra uno prodotto dal compilatore javac. Ho trovato in passato che il codice scritto usando hamcrest non verrà compilato sotto javac. Lo stesso codice verrà compilato correttamente, ad esempio, nel compilatore Eclipse.

Penso che i generici di Hamcrest stiano esercitando casi d'angolo in generici che javac non può affrontare.

+0

Wow, interessante. Quindi stai dicendo che il codice sopra è un codice java legittimo? – ripper234

+2

No, sto dicendo che javac a volte rifiuta il codice java legittimo, e hamcrest ne è una causa comune. – skaffman

3

Prova

assertThat(actual, hasItems(expected.toArray(new Integer[0]))); 

per soddisfare la firma matcher. No Eclipse in giro, quindi potrebbe non funzionare.

21

hasItems verifica che una raccolta contenga alcuni elementi, non che 2 collezioni siano uguali, basta usare le normali asserzioni di uguaglianza per quello. Quindi, o assertEquals (a, b) oppure utilizzando assertThat

import static org.junit.Assert.assertThat; 
import static org.hamcrest.CoreMatchers.is; 

ArrayList<Integer> actual = new ArrayList<Integer>(); 
ArrayList<Integer> expected = new ArrayList<Integer>(); 
actual.add(1); 
expected.add(2); 
assertThat(actual, is(expected)); 

In alternativa, utilizzare la contiene Matcher, che controlla che un Iterable contiene elementi in un ordine specifico

import static org.junit.Assert.assertThat; 
import static org.hamcrest.Matchers.contains; 

ArrayList<Integer> actual = new ArrayList<Integer>(); 
actual.add(1); 
actual.add(2); 
assertThat(actual, contains(1, 2)); // passes 
assertThat(actual, contains(3, 4)); // fails 

Se non si cura di l'ordine utilizza invece containsInAnyOrder.

0
ArrayList<Integer> expected = new ArrayList<Integer>(); 
expected.add(1); 
expected.add(2); 
hasItems(expected); 

hasItems (T..t) è in fase di espansione dal compilatore per:

hasItems(new ArrayList<Integer>[]{expected}); 

si passa un singolo array elemento contenente un ArrayList. Se si modifica ArrayList in una matrice, il codice funzionerà.

Integer[] expected = new Integer[]{1, 2}; 
hasItems(expected); 

Questo sarà ampliato a:

hasItems(1, 2); 
1

Per questi casi quando il codice si compila in Eclipse, ma javac mostra errori Si prega di aiuto hamcrest fornendo esplicitamente tipo di parametro per esempio Matchers.hasItem()

2

Ho appena incontrato lo stesso problema e il seguente trucco ha funzionato per me:

  • uso import static org.hamcrest.Matchers.hasItems
  • hanno biblioteca hamcrest prima di JUnit nel classpath (build percorso -> ordine ed esportazione)
52

Ho appena eseguito questo post cercando di risolvere il problema per me stesso. Mi ha dato abbastanza informazioni per risolverlo.

Si può dare il compilatore appena sufficiente per convincerlo a compilare lanciando il valore restituito da hasItems ad un Matcher (grezzo), per esempio:

ArrayList<Integer> actual = new ArrayList<Integer>(); 
ArrayList<Integer> expected = new ArrayList<Integer>(); 
actual.add(1); 
expected.add(2); 
assertThat(actual, (Matcher) hasItems(expected)); 

Solo nel caso qualcun altro soffre ancora ...

Modifica da aggiungere: Nonostante i voti positivi, questa risposta è errata, come indicato da Arend in seguito. Il corretta risposta è quello di trasformare l'atteso in un array di numeri interi, come hamcrest si aspetta:

ArrayList<Integer> actual = new ArrayList<Integer>(); 
    ArrayList<Integer> expected = new ArrayList<Integer>(); 
    actual.add(1); 
    expected.add(2); 
    assertThat(actual, hasItems(expected.toArray(new Integer[expected.size()]))); 
+0

Non ho provato questa risposta dato che molto tempo fa ho perso questo codice sorgente (le aziende trasferite due volte), ma ti ho dato un pollice in su per resuscitare questo. – ripper234

+1

Buon consiglio. Sembra l'unico modo "semplice" di usare assertThat() con qualsiasi strumento di raccolta delle raccolte poiché Hamcrest ha modificato i generici di match match su invece di solo .. – Frans

+0

Ho desiderato che "hasItems" corrispondesse anche all'ordine. Che sembra non farlo. –

2

È possibile ottenere questo errore se si tenta di sostituire hamcrest di JUnit con una versione più recente. Ad esempio, utilizzando junit-dep insieme a hamcrest 1.3 è necessario utilizzare assertThat da hamcrest anziché jUnit.

Quindi la soluzione è quella di utilizzare

import static org.hamcrest.MatcherAssert.assertThat;

invece di

import static org.junit.Assert.assertThat;