918 Stimmen

Rückgabe eines übergebenen Arguments durch eine nachgebildete Methode

Betrachten Sie eine Methodensignatur wie:

public String myFunction(String abc);

Kann Mockito dabei helfen, die gleiche Zeichenfolge zurückzugeben, die die Methode erhalten hat?

13voto

LazR Punkte 521

Diese Frage ist ziemlich alt, aber ich denke, sie ist immer noch aktuell. Auch die akzeptierte Antwort funktioniert nur für String. Inzwischen gibt es Mockito 2.1 und einige Importe haben sich geändert, daher möchte ich meine aktuelle Antwort teilen:

import static org.mockito.AdditionalAnswers.returnsFirstArg;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

@Mock
private MyClass myClass;

// this will return anything you pass, but it's pretty unrealistic
when(myClass.myFunction(any())).then(returnsFirstArg());
// it is more "life-like" to accept only the right type
when(myClass.myFunction(any(ClassOfArgument.class))).then(returnsFirstArg());

Die myClass.myFunction würde wie folgt aussehen:

public class MyClass {
    public ClassOfArgument myFunction(ClassOfArgument argument){
        return argument;
    }  
}

7voto

Lachezar Balev Punkte 10847

Dieser Artikel ist schon etwas älter, aber ich bin hierher gekommen, weil ich das gleiche Problem hatte. Ich verwende JUnit, aber dieses Mal in einer Kotlin-App mit mockk. Ich poste hier ein Beispiel als Referenz und zum Vergleich mit dem Java-Pendant:

@Test
fun demo() {
  // mock a sample function
  val aMock: (String) -> (String) = mockk()

  // make it return the same as the argument on every invocation
  every {
    aMock.invoke(any())
  } answers {
    firstArg()
  }

  // test it
  assertEquals("senko", aMock.invoke("senko"))
  assertEquals("senko1", aMock.invoke("senko1"))
  assertNotEquals("not a senko", aMock.invoke("senko"))
}

7voto

Cyril Cherian Punkte 31737

Sie können dies erreichen, indem Sie ArgumentCaptor

Stellen Sie sich vor, Sie haben eine Bohnenfunktion wie diese.

public interface Application {
  public String myFunction(String abc);
}

Dann in Ihrer Testklasse:

//Use ArgumentCaptor to capture the value
ArgumentCaptor<String> param = ArgumentCaptor.forClass(String.class);

when(mock.myFunction(param.capture())).thenAnswer(new Answer<String>() {
    @Override
    public String answer(InvocationOnMock invocation) throws Throwable {
      return param.getValue();//return the captured value.
    }
  });

OR wenn Sie Fan von Lambda einfach tun:

//Use ArgumentCaptor to capture the value
ArgumentCaptor<String> param = ArgumentCaptor.forClass(String.class);

when(mock.myFunction(param.capture()))
    .thenAnswer((invocation) -> param.getValue());

Zusammenfassung: Verwenden Sie argumentcaptor, um den übergebenen Parameter zu erfassen. Geben Sie später in der Antwort den mit getValue erfassten Wert zurück.

6voto

fl0w Punkte 2940

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

ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
verify(mock).myFunction(argument.capture());
assertEquals("the expected value here", argument.getValue());

Der Wert des Arguments ist natürlich über argument.getValue() für weitere Manipulationen/Überprüfungen/was auch immer zugänglich.

4voto

martin Punkte 1939

Ich verwende etwas Ähnliches (im Grunde ist es derselbe Ansatz). Manchmal ist es nützlich, ein Mock-Objekt zu haben, das eine vordefinierte Ausgabe für bestimmte Eingaben zurückgibt. Das geht so:

private Hashtable<InputObject,  OutputObject> table = new Hashtable<InputObject, OutputObject>();
table.put(input1, ouput1);
table.put(input2, ouput2);

...

when(mockObject.method(any(InputObject.class))).thenAnswer(
       new Answer<OutputObject>()
       {
           @Override
           public OutputObject answer(final InvocationOnMock invocation) throws Throwable
           {
               InputObject input = (InputObject) invocation.getArguments()[0];
               if (table.containsKey(input))
               {
                   return table.get(input);
               }
               else
               {
                   return null; // alternatively, you could throw an exception
               }
           }
       }
       );

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X