Mockito: Methoden die Class-Objekte liefern: Unterschied zwischen den Versionen
Keine Bearbeitungszusammenfassung |
Keine Bearbeitungszusammenfassung |
||
Zeile 15: | Zeile 15: | ||
Mockito.when(foo.klasse()).thenReturn(Integer.class); | Mockito.when(foo.klasse()).thenReturn(Integer.class); | ||
}} | }} | ||
Läuft aber auf einen Fehler. | Läuft aber auf einen Fehler. Auf die Fehler-Ursache kommen wir später zurück, erstmal sehen was sich tun läßt. Es giebt mindestens drei work arounds. | ||
Der Fehler mit dem uns der Compiler konfrontiert sieht so aus: | Der Fehler mit dem uns der Compiler konfrontiert sieht so aus: | ||
The method thenReturn(Class<capture#3-of ?>) in the type OngoingStubbing<Class<capture#3-of ?>> is not | The method thenReturn(Class<capture#3-of ?>) in the type OngoingStubbing<Class<capture#3-of ?>> is not | ||
applicable for the arguments (Class<Integer>) | applicable for the arguments (Class<Integer>) | ||
== Den return-Wert casten == | |||
Der naheligende Versuch, Den Paraneter von {{java|Integer.class}} auf {{java|Class<?>}} zu casten um den Return-Wert des Mocks mit der gemockten Methode in Deckung zu bringen fruchtet nicht -- wo also hincasten? Das Problem hat anscheinend etwas mit der Parametrisierung des Typs der Klasse {{java|Class}}, verwendet man stattdessen den raw type funktionierts: | |||
{{java|code= | {{java|code= | ||
Mockito.when(foo.klasse()).thenReturn((Class) Integer.class); | Mockito.when(foo.klasse()).thenReturn((Class) Integer.class); | ||
}} | }} | ||
Allerdings warnt der Compiler dann vor der Verwendung des raw types. Wen das nicht anficht, der kann's so machen. | Allerdings warnt der Compiler dann vor der Verwendung des raw types. Wen das nicht anficht, der kann's so machen. | ||
== Die when-Methode parametrisieren == | |||
Schaut man sich die when-Methode genauer an findet man diese Signatur: | |||
{{java|code= | |||
public static <T> OngoingStubbing<T> when(T methodCall) | |||
}} | |||
Unsere bisherigen Ansätze haben den Typ-Parameter ignoriert und dem Compiler überlassen herauszufinden wie das {{java|T}} hier zu interpretieren ist. Helfen wir dem Compiler auf die Sprünge und geben den Typ -- es handelt sich um den Return-Typ der gemockten Methode -- explizit an: | |||
{{java|code= | |||
Mockito.<Class<?>>when(foo.klasse()).thenReturn(Integer.class); | |||
}} | |||
und schon geht's | |||
== doReturn...when == | == doReturn...when == | ||
Eine weitere elegante Methode führt über die Umgehung des when...then-Konstrukts. Ohne lange Vorrede: | |||
{{java|code= | {{java|code= | ||
Mockito.doReturn(Integer.class).when(foo).klasse(); | Mockito.doReturn(Integer.class).when(foo).klasse(); | ||
}} | }} | ||
Dieses Konstrukt vermeidet auch die Compiler-Warnung. | Dieses Konstrukt vermeidet auch die Compiler-Warnung. | ||
== Zur Ursache == | |||
Das Problem liegt augenscheinlich am Unvermögen des Compilers den richtigen Typ für den Typ-Parameter zu ermitteln. Zumindest schafft der Compiler es nicht die Typen {{java|Class<?>}} und {{java|Class}} zur Deckung zu bringen. Die {{java|when}}-Methode haben wir oben schon gesehen, wie sieht das beim {{java|doReturn}} aus? | |||
{{java|code= | |||
public static Stubber doReturn(Object toBeReturned) | |||
}} | |||
Der Typ des Arguments {{java|Integer.class}} das an {{java|doReturn}} übergeben wird, wird irrelevant durch den Parameter-Typ {{java|Object}} und an {{java|Stubber}} nicht weitergegeben. Die Methode {{java|when}} der Interface {{java|Stubber}} ist so definiert: | |||
{{java|code= | |||
<T> T when(T mock); | |||
}} | |||
Hier interessiert der Rückgabe-Typ der gemockten Methode überhaupt nicht mehr, {{java|T}} bezeichnet nämlich den Typ des Mocks. Beim doReturn...when-Konstrukt taucht das Problem daher nicht auf. |
Aktuelle Version vom 23. Juni 2021, 18:53 Uhr
Mocken von Methoden die Class-Objekte liefern
Ein spezielles Problem ist das mocken von Methoden die Class
-Objekte liefern.
Betrachten wir dazu folgende Klasse:
class Foo { Class<?> klasse() { return String.class; } }
Das Mocken der Methode klasse
könnte dann so aussehen:
Mockito.when(foo.klasse()).thenReturn(Integer.class);
Läuft aber auf einen Fehler. Auf die Fehler-Ursache kommen wir später zurück, erstmal sehen was sich tun läßt. Es giebt mindestens drei work arounds.
Der Fehler mit dem uns der Compiler konfrontiert sieht so aus:
The method thenReturn(Class<capture#3-of ?>) in the type OngoingStubbing<Class<capture#3-of ?>> is not applicable for the arguments (Class<Integer>)
Den return-Wert casten
Der naheligende Versuch, Den Paraneter von Integer.class
auf Class<?>
zu casten um den Return-Wert des Mocks mit der gemockten Methode in Deckung zu bringen fruchtet nicht -- wo also hincasten? Das Problem hat anscheinend etwas mit der Parametrisierung des Typs der Klasse Class
, verwendet man stattdessen den raw type funktionierts:
Mockito.when(foo.klasse()).thenReturn((Class) Integer.class);
Allerdings warnt der Compiler dann vor der Verwendung des raw types. Wen das nicht anficht, der kann's so machen.
Die when-Methode parametrisieren
Schaut man sich die when-Methode genauer an findet man diese Signatur:
public static <T> OngoingStubbing<T> when(T methodCall)
Unsere bisherigen Ansätze haben den Typ-Parameter ignoriert und dem Compiler überlassen herauszufinden wie das T
hier zu interpretieren ist. Helfen wir dem Compiler auf die Sprünge und geben den Typ -- es handelt sich um den Return-Typ der gemockten Methode -- explizit an:
Mockito.<Class<?>>when(foo.klasse()).thenReturn(Integer.class);
und schon geht's
doReturn...when
Eine weitere elegante Methode führt über die Umgehung des when...then-Konstrukts. Ohne lange Vorrede:
Mockito.doReturn(Integer.class).when(foo).klasse();
Dieses Konstrukt vermeidet auch die Compiler-Warnung.
Zur Ursache
Das Problem liegt augenscheinlich am Unvermögen des Compilers den richtigen Typ für den Typ-Parameter zu ermitteln. Zumindest schafft der Compiler es nicht die Typen Class<?>
und Class
zur Deckung zu bringen. Die when
-Methode haben wir oben schon gesehen, wie sieht das beim doReturn
aus?
public static Stubber doReturn(Object toBeReturned)
Der Typ des Arguments Integer.class
das an doReturn
übergeben wird, wird irrelevant durch den Parameter-Typ Object
und an Stubber
nicht weitergegeben. Die Methode when
der Interface Stubber
ist so definiert:
<T> T when(T mock);
Hier interessiert der Rückgabe-Typ der gemockten Methode überhaupt nicht mehr, T
bezeichnet nämlich den Typ des Mocks. Beim doReturn...when-Konstrukt taucht das Problem daher nicht auf.