2017-11-15 10 views
0

Ich habe einen Getter eine Liste mit einem Wildcard-Rückkehr:AssertJ `containsExactly` Behauptung auf Liste mit Wildcard

import java.util.List; 

public interface Foo { 
    List<? extends Bar> getList(); 
} 

Wo Bar eine andere Schnittstelle ist.

Wenn ich schreibe eine Behauptung mit AssertJ wie folgt aus:

assertThat(foo.getList()).containsExactly(bar1, bar3); 

EDIT: meine komplette Nutzung der Kette ist ein usingElementComparator und Comparator<Bar> bereitzustellen, um die erwartete Bar Instanzen zu vergleichen.

Comparator<Bar> comparator = createBarComparator() 
assertThat(foo.getList()).usingElementComparator(comparator).containsExactly(bar1, bar3); 

Ich erhalte diese Kompilierungsfehler:

The method containsExactly(capture#46-of ? extends Bar...) in the type ListAssert is not applicable for the arguments (Bar, Bar)


Meine erste Lösung ist, um das Ergebnis zu werfen:

assertThat((List<Bar>)foo.getList()).containsExactly(bar1, bar3); 

Dann bekomme ich eine Warnung:

Type safety: Unchecked cast from List to List

Warnung kann mit @SuppressWarnings("unchecked") entfernt werden, aber die Besetzung in der Mitte macht die Behauptung nicht wirklich lesbar.


Meine zweite Lösung ist es, den Wert des ELEMENT generische Parameter, um anzuzeigen:

Assertions.<Bar>assertThat(foo.getList()).containsExactly(bar1, bar3); 

ein wenig besser, aber auch nicht so schön (kein statischer Import möglich, der Anfang der Zeile nicht erleichtern die Lesbarkeit)


ich glaube, ich für eine andere assertThat Verfahren zur Liste suchen, wo der Klassentyp als zweiter Parameter angegeben werden können:

@CheckReturnValue 
public static <ELEMENT> ListAssert<ELEMENT> assertThat(List<? extends ELEMENT> actual, Class<ELEMENT> c) { 
    return AssertionsForInterfaceTypes.assertThat(actual); 
} 

Auf diese Weise sollte ich so etwas schreiben können:

Assertions.assertThat(foo.getList(), Bar.class).containsExactly(bar1, bar3); 

Antwort

1

Das war früher mit dem Oracle JDK 7 Compiler arbeiten, aber das war tatsächlich ein Fehler im Compiler, dies wurde gefixt in Java 8 JDK, so dass der Kompilierungsfehler das normale Verhalten ist (die Fehlerreferenz kann jedoch nicht gefunden werden).

Ich würde gerne unterstützen, aber ich bin mir nicht sicher, dass dies in AssertJ möglich ist, außer durch Entfernen aller generics Verwendung in Sammlungen Assertions.

assertThat(List, Class) existiert bereits aber für einen anderen Zweck also kein Glück für diese Option.

Eine mögliche Hack ist Ihre eigene assertThat Methode so zu definieren:

public static <T> ListAssert<Object> assertThat(final List<T> list) { 
    return Assertions.assertThat(list); 
} 

Der Trick ein ListAssert<Object> zurückkehren zu.

Obwohl ich die Begründung des Kompilierungsfehlers verstehe, stimme ich ihm für die Nur-Lese-Methode nicht zu.

+0

Vielen Dank für Ihre ausführliche Antwort. Entfernen Sie nicht alle generischen Verwendungszwecke in Auflistungsassertionen. Sie sind zu 95% korrekt und hilfreich. Die Rückgabe einer 'ListAssert ' funktioniert nicht für mich, weil ich auch eine 'usingElementComparator' Methode in der Kette verwende (siehe aktualisierte Frage). Ich könnte gehen mit eigenen 'assertThatListOf (Klasse, Liste)' Übrigens, * DANKE * für AssertJ, Es ist eine großartige Bibliothek! – Jmini

+0

Danke für die freundlichen Worte, geschätzt. –

Verwandte Themen