Verwendung der generischen Methode "any ()" von Mockito

194

Ich habe eine Schnittstelle mit einer Methode, die ein Array von erwartet Foo:

public interface IBar {
  void doStuff(Foo[] arr);
}

Ich verspotte diese Schnittstelle mit Mockito und möchte behaupten, dass sie doStuff()aufgerufen wird, aber ich möchte nicht überprüfen, welche Argumente übergeben werden - "egal".

Wie schreibe ich den folgenden Code mit any()der generischen Methode anstelle von anyObject()?

IBar bar = mock(IBar.class);
...
verify(bar).doStuff((Foo[]) anyObject());
ripper234
quelle

Antworten:

111

Seit Java 8 können Sie die argumentlose anyMethode verwenden, und das Typargument wird vom Compiler abgeleitet:

verify(bar).doStuff(any());

Erläuterung

Das Neue in Java 8 ist, dass der Zieltyp eines Ausdrucks verwendet wird, um Typparameter seiner Unterausdrücke abzuleiten. Vor Java 8 wurden nur Argumente für Methoden verwendet, die für die Inferenz von Typparametern verwendet wurden (meistens).

In diesem Fall ist der Parametertyp von doStuffder Zieltyp für any(), und der Rückgabewerttyp von any()wird entsprechend diesem Argumenttyp ausgewählt.

Dieser Mechanismus wurde in Java 8 hauptsächlich hinzugefügt, um Lambda-Ausdrücke kompilieren zu können, verbessert jedoch allgemein die Typinferenzen.


Primitive Typen

Dies funktioniert leider nicht mit primitiven Typen:

public interface IBar {
    void doPrimitiveStuff(int i);
}

verify(bar).doPrimitiveStuff(any()); // Compiles but throws NullPointerException
verify(bar).doPrimitiveStuff(anyInt()); // This is what you have to do instead

Das Problem ist, dass der Compiler Integerals Rückgabewert von ableitet any(). Mockito ist sich dessen nicht bewusst (aufgrund der Typlöschung) und gibt den Standardwert für Referenztypen zurück null. Die Laufzeit versucht, den Rückgabewert zu entpacken, indem sie die intValueMethode aufruft , bevor sie an übergeben wird doStuff, und die Ausnahme wird ausgelöst.

Lii
quelle
Ich bin jedes Mal angenehm überrascht, wenn diese Antwort positiv bewertet wird! Ich hätte vermutet, dass die Frage seit Java 8 nicht viel Aufmerksamkeit erregen würde, da die anyMethode einfach funktionieren sollte. Sie suchen keine Antwort für Dinge, die nur funktionieren!
Lii
Ich bin hierher gekommen, weil ich nicht wusste, warum mein Code nicht funktioniert hat, any()aber in Ordnung war anyBoolean(), was der letzte Teil Ihrer Antwort wunderschön beleuchtet.
AdrienW
274

Das sollte funktionieren

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;

verify(bar).DoStuff(any(Foo[].class));
Jitter
quelle
31
Nur für den Fall, dass jemand es in Scala braucht:verify(bar).DoStuff(any[Array[Foo]])
Tolitius
6
Ich hatte ein Problem mit dem Import, ich habe bei meinen Importen any () von hamcrest verwendet und es kollidierte mit dem von mockito.
Doppelgänger
4
Bitte werfen Sie einen Blick in die API, das Klassenargument wird nur zum Casting verwendet, die Methode akzeptiert immer noch jede Art von Objekt! site.mockito.org/mockito/docs/current/org/mockito/… . Verwenden Sie für diesen Fall isA () site.mockito.org/mockito/docs/current/org/mockito/… .
Thilko
1
Diese Klasse ist jetzt veraltet, um einen Namenskonflikt mit Hamcrest zu vermeiden. Verwenden Sie org.mockito.ArgumentMatchers
leo9r
12

Sie können dafür verwenden Mockito.isA():

import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.verify;

verify(bar).doStuff(isA(Foo[].class));

http://site.mockito.org/mockito/docs/current/org/mockito/Matchers.html#isA(java.lang.Class)

Thilko
quelle
Dies ist die richtige Antwort. Die Verwendung von any (Clazz) ist völlig falsch.
Surasin Tancharoen
3
@SurasinTancharoen Eigentlich ist jede (Klasse) nur ein Alias ​​von isA (Klasse) (siehe die Dokumente). Es ist also überhaupt nicht falsch.
jmiserez
8

Da ich diese Funktion für mein aktuelles Projekt verwenden musste (an einem Punkt haben wir von 1.10.19 aktualisiert), nur um die Benutzer (die bereits die Mockito-Core-Version 2.1.0 oder höher verwenden ) auf dem neuesten Stand zu halten, die statische Methoden aus den obigen Antworten sollten aus der ArgumentMatchersKlasse entnommen werden :

import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.ArgumentMatchers.any;

Bitte beachten Sie dies, wenn Sie planen, Ihre Mockito-Artefakte auf dem neuesten Stand zu halten, da diese Klasse möglicherweise ab Version 3 verfügbar ist. Diese Klasse existiert möglicherweise nicht mehr:

Ab 2.1.0 gibt Javadoc von org.mockito.Matchers Folgendes an:

Verwenden Sie org.mockito.ArgumentMatchers. Diese Klasse ist jetzt veraltet, um einen Namenskonflikt mit der Hamcrest * org.hamcrest.Matchers -Klasse zu vermeiden . Diese Klasse wird wahrscheinlich in Version 3.0 entfernt.

Ich habe einen kleinen Artikel über Mockito-Wildcards geschrieben, wenn Sie weiterlesen möchten .

Maciej Kowalski
quelle
Wie kann ich org.mockito.ArgumentMatcher in Scala importieren? Ich habe versucht, org.mockito.ArgumentMatcher.any zu importieren. Ich erhalte die Fehlermeldung `value any ist kein Mitglied des Objekts org.mockito.ArgumentMatcher
Manu Chadha
Könnten Sie mir bitte sagen, was das Äquivalent in Version 3.0 ist?
Manu Chadha
Wir werden es wissen, sobald es veröffentlicht wird;)
Maciej Kowalski