Mockito-Rückrufe und Abrufen von Argumentwerten

87

Ich habe kein Glück, dass Mockito Funktionsargumentwerte erfasst! Ich verspotte einen Suchmaschinenindex und anstatt einen Index zu erstellen, verwende ich nur einen Hash.

// Fake index for solr
Hashmap<Integer,Document> fakeIndex;

// Add a document 666 to the fakeIndex
SolrIndexReader reader = Mockito.mock(SolrIndexReader.class);

// Give the reader access to the fake index
Mockito.when(reader.document(666)).thenReturn(document(fakeIndex(666))

Ich kann keine beliebigen Argumente verwenden, da ich die Ergebnisse von Abfragen teste (dh welche Dokumente sie zurückgeben). Ebenso möchte ich nicht für jedes Dokument einen bestimmten Wert angeben und eine Zeile haben!

Mockito.when(reader.document(0)).thenReturn(document(fakeIndex(0))
Mockito.when(reader.document(1)).thenReturn(document(fakeIndex(1))
....
Mockito.when(reader.document(n)).thenReturn(document(fakeIndex(n))

Ich habe mir den Abschnitt mit Rückrufen auf der Seite Using Mockito angesehen . Leider ist es kein Java und ich konnte meine eigene Interpretation davon nicht in Java zum Laufen bringen.

BEARBEITEN (zur Verdeutlichung): Wie kann ich Mockito dazu bringen, ein Argument X zu erfassen und an meine Funktion zu übergeben? Ich möchte, dass der genaue Wert (oder die Referenz) von X an die Funktion übergeben wird.

Ich möchte nicht alle Fälle aufzählen, und ein beliebiges Argument funktioniert nicht, da ich für verschiedene Abfragen auf unterschiedliche Ergebnisse teste.

Die Mockito-Seite sagt

val mockedList = mock[List[String]]
mockedList.get(anyInt) answers { i => "The parameter is " + i.toString } 

Das ist kein Java, und ich weiß nicht, wie ich es in Java übersetzen oder was auch immer passiert ist, an eine Funktion übergeben soll.

nflacco
quelle
Ich bin mir nicht sicher, ob ich genau verstehe, was für Sie fehlschlägt. Ihr Aufruf an Mockito.when(reader.document(666)).thenReturn(document(fakeIndex(666))sollte das Scheinobjekt für Sie einrichten. Was passiert, wenn Sie anrufen reader.document(666)?
koffeinhaltig
Der 666 funktioniert gut. Ich möchte jedoch in der Lage sein, eine bestimmte Zahl X einzugeben und das Ergebnis von fakeIndex (X) zu erhalten. Ich habe eine große Anzahl potenzieller Dokumente, die auf Abfragen getestet werden müssen, und ich möchte nicht alle eingeben.
Nflacco

Antworten:

103

Ich habe Mockito noch nie benutzt, möchte aber lernen, also geht es weiter. Wenn jemand weniger ahnungslos als ich antwortet, versuchen Sie zuerst seine Antwort!

Mockito.when(reader.document(anyInt())).thenAnswer(new Answer() {
 public Object answer(InvocationOnMock invocation) {
     Object[] args = invocation.getArguments();
     Object mock = invocation.getMock();
     return document(fakeIndex((int)(Integer)args[0]));
     }
 });
Ed Staub
quelle
2
Ich habe gerade den Link auf der rechten Seite zu Mockito bemerkt : Wie man eine Methode dazu bringt, ein Argument zurückzugeben, das an sie übergeben wurde . Sieht so aus, als wäre ich nah dran, wenn nicht genau richtig.
Ed Staub
Starke Benutzerreputation (666) zur ursprünglichen Fragekorrelation! Das hat sehr gut funktioniert. Die einzige Änderung, die ich vorgenommen habe, um das Kompilieren von
Inhalten zu ermöglichen
54

Schauen Sie sich ArgumentCaptors an:

https://site.mockito.org/javadoc/current/org/mockito/ArgumentCaptor.html

ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
Mockito.when(reader.document(argument.capture())).thenAnswer(
  new Answer() {
    Object answer(InvocationOnMock invocation) {
      return document(argument.getValue());
    }
  });
qualidafial
quelle
3
Wow, ich wusste nicht, dass du ArgumentCaptors zum Stubben verwenden kannst. Es gibt jedoch eine große alte Warnung in diesem Link. Mit Vorsicht fortfahren.
Unschuldig
3
Ja, du hast recht. Captors sollten nur mit Überprüfungen verwendet werden.
Qualidafial
39

Möglicherweise möchten Sie verify () in Kombination mit dem ArgumentCaptor verwenden, um die Ausführung im Test sicherzustellen, und dem ArgumentCaptor, um die Argumente auszuwerten:

ArgumentCaptor<Document> argument = ArgumentCaptor.forClass(Document.class);
verify(reader).document(argument.capture());
assertEquals(*expected value here*, argument.getValue());

Der Wert des Arguments ist offensichtlich über argument.getValue () zugänglich, um weitere Manipulationen / Überprüfungen durchzuführen oder was auch immer Sie tun möchten.

fl0w
quelle
2
beste Antwort: direkt, leicht zu verstehen
Radu Cugut
Beantwortet die Frage nicht. Frage ist über Mockito.when und nicht verifizieren.
seBaka28
@ seBaka28 Die beste Lösung, um Argumente zu erhalten, ist ein Argument-Captor. ArgumentCaptors wird dringend empfohlen, von den Autoren von Mockito zur Überprüfung verwendet zu werden. Daher wollte ich eine vollständige perspektivische Antwort geben. Wenn Sie sich dafür entscheiden, sie nicht zu verwenden, ist dies Ihre Wahl, wird jedoch nicht empfohlen. EDIT: Ich verstehe nicht, wie dies eine Ablehnung rechtfertigt, aber das ist auch Ihre Entscheidung.
7.
Weil es die Frage nicht beantwortet. Ja, ArgumentCaptor ist großartig, wenn Sie das Argument erfassen möchten, aber Sie können es nicht in Verbindung mit when (...). ThenReturn () verwenden, was OP versucht: Basierend auf einem bestimmten Parameter, einem verspotteten Dienst soll ein bestimmtes Objekt zurückgeben.
seBaka28
Genau das ist hier gefragt. Mit Argument-Captoren können Sie genau dies tun. Bitte probieren Sie es einfach selbst aus.
fl0w vor
13

Mit Java 8 könnte dies ungefähr so ​​aussehen:

Mockito.when(reader.document(anyInt())).thenAnswer(
  (InvocationOnMock invocation) -> document(invocation.getArguments()[0]));

Ich gehe davon aus, dass dies documenteine Karte ist.

Jean-François Beauchef
quelle