2013-09-04 8 views
6

Der Matcher IsIterableContainingInAnyOrder zwei Überlastungen für die statische Factory-Methode hat containsInAnyOrder (beide haben den Rückgabetyp Matcher<java.lang.Iterable<? extends T>>):Widersprüchliche Überlastungen für hamcrest Matcher

  1. containsInAnyOrder(java.util.Collection<Matcher<? super T>> itemMatchers)
  2. containsInAnyOrder(Matcher<? super T>... itemMatchers)

Betrachten wir nun die folgenden Programm:

import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; 
import static org.hamcrest.core.IsEqual.equalTo; 
import static org.junit.Assert.assertThat; 

import java.util.Arrays; 

import org.junit.Test; 

public class SomeTest { 

    @SuppressWarnings("unchecked") 
    @Test 
    public void foo() { 
     assertThat(Arrays.asList("foo","bar"), 
         containsInAnyOrder(equalTo("foo"), equalTo("bar"))); 
    } 

} 

Wenn dies als JUnit-Test ausgeführt wird, wird es wie erwartet übergeben. Es verwendet die oben gezeigte zweite Überlast von containsInAnyOrder.

Nun, wenn ich ändern, um die Behauptung zu dieser (was genau das Beispiel in der documentation of the first overload gegeben Spiele):

assertThat(Arrays.asList("foo","bar"), 
      containsInAnyOrder(Arrays.asList(equalTo("foo"), equalTo("bar")))); 
           ^^^^^^^^^^^^^^ 

kompilieren nicht mehr, weil jetzt der Compiler den Rückgabetyp von containsInAnyOrder folgert zu be

Matcher<Iterable<? extends List<Matcher<String>>>> 

Es scheint, als ob der Compiler immer noch die zweite Überladung wählt. Wenn es die erste verwendet, sollte das Beispiel funktionieren. Warum verhält es sich so? Wie kann ich das schaffen?

Ich benutze Hamcrest 1.3 und Oracle Java 1.7.

Antwort

4

Es entspricht tatsächlich beiden überladenen Methoden. Ich bin mir nicht sicher, warum genau die erste ausgewählt wurde, aber Sie können einen Hinweis geben, um die richtige Methode auszuwählen.

Durch Gießen des Arguments Collection:

assertThat(Arrays.asList("foo","bar"), 
     containsInAnyOrder((Collection)Arrays.asList(equalTo("foo"), equalTo("bar")))); 

oder durch die generische Typen T als <String> Angabe (nicht mit statischem Import arbeiten, obwohl):

assertThat(Arrays.asList("foo","bar"), 
     IsIterableContainingInAnyOrder.<String>containsInAnyOrder(Arrays.asList(equalTo("foo"), equalTo("bar")))); 
+0

ich die zweite Version für Typsicherheit empfehlen.Zusätzlich können Sie 'Matcher 'schreiben. containsInAnyOrder' statt 'IsIterableContainingInAnyOrder. enthältInAnyOrder'. – eee

2

Dies ist auch ein etwas härter, wenn Sie Ihre eigenen Objekte und nicht einfache Strings zusammenbringen, um Generika zum Laufen zu bringen. Wenn Sie die varargs containsInAnyOrder(Matcher<? super T>... itemMatchers) wie im ersten Beispiel der Frage verwenden, erhalten Sie eine ungeprüfte Generics-Array-Erstellung für Varargs Parameter Warnung. Zum Beispiel:

assertThat(myDTOList, 
    containsInAnyOrder(sameStateAs(expectedMyDTO1), sameStateAs(expectedMyDTO2)); 

Ein Weg, um dann das Problem zu lösen das OP in der Frage erwähnt, ist Ihre Sammlung von Matcher wie folgt zu definieren:

Collection<Matcher<? super MyDTO>> expectedMyDTOs = 
    Arrays.<Matcher<? super MyDTO>>asList(sameStateAs(expectedMyDTO1), sameStateAs(expectedMyDTO2)); 

// Use like this: 
assertThat(myDTOList, 
    containsInAnyOrder(expectedMyDTOs); 
+0

wow, '? Super MyDTO hat es geschafft. '? Super Objekt' hat nicht:) vielen Dank! – borowis

2

Mit hamcrest 1.3 Sie in der Lage sind zu verwenden, Matchers Klasse statt IsIterableContainingInAnyOrder direkt wie von @eee erwähnt. Matchers ruft eigentlich nur IsIterableContainingInAnyOrder für Sie auf.

import static org.hamcrest.core.IsEqual.equalTo; 
import static org.junit.Assert.assertThat; 

import org.hamcrest.Matchers; 
import java.util.Arrays; 
import org.junit.Test; 

public class SomeTest 
{ 
    @Test 
    public void foo() { 
     assertThat(Arrays.asList("foo","bar"), 
      Matchers.<OrderValidationStep>containsInAnyOrder("foo", "bar")); 
    } 
} 

Beachten Sie, dass kein statischen Import verwenden können, wenn Sie Ihren Anruf containsInAnyOrder auf Type wollen, und dies beseitigt die Notwendigkeit hinzufügen @SuppressWarnings("unchecked")

Verwandte Themen