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?

1388voto

Steve Punkte 17080

Seit Mockito 1.9.5+ und Java 8+

Sie können einen Lambda-Ausdruck verwenden, z. B.:

when(myMock.myFunction(anyString())).thenAnswer(i -> i.getArguments()[0]);

Donde i ist eine Instanz von InvocationOnMock .

Für ältere Versionen

Sie können eine Antwort in Mockito erstellen. Nehmen wir an, wir haben eine Schnittstelle namens MyInterface mit einer Methode myFunction.

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

Hier ist die Testmethode mit einer Mockito-Antwort:

public void testMyFunction() throws Exception {
    MyInterface mock = mock(MyInterface.class);
    when(mock.myFunction(anyString())).thenAnswer(new Answer<String>() {
    @Override
    public String answer(InvocationOnMock invocation) throws Throwable {
        Object[] args = invocation.getArguments();
        return (String) args[0];
    }
    });

    assertEquals("someString",mock.myFunction("someString"));
    assertEquals("anotherString",mock.myFunction("anotherString"));
}

686voto

Dawood ibn Kareem Punkte 72413

Wenn Sie Mockito 1.9.5 oder höher haben, gibt es eine neue statische Methode, mit der Sie die Answer Objekt für Sie. Sie müssen etwas schreiben wie

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

when(myMock.myFunction(anyString())).then(returnsFirstArg());

oder alternativ

doAnswer(returnsFirstArg()).when(myMock).myFunction(anyString());

Beachten Sie, dass die returnsFirstArg() Methode ist statisch in der AdditionalAnswers Klasse, die neu in Mockito 1.9.5 ist; Sie benötigen also den richtigen statischen Import.

100voto

Paweł Dyda Punkte 18030

Mit Java 8 ist es möglich, auch mit älteren Versionen von Mockito eine einzeilige Antwort zu erstellen:

when(myMock.myFunction(anyString()).then(i -> i.getArgumentAt(0, String.class));

Natürlich ist dies nicht so nützlich wie die Verwendung von AdditionalAnswers von David Wallace vorgeschlagen, könnte aber nützlich sein, wenn Sie Argumente "on the fly" umwandeln wollen.

43voto

yiwei Punkte 3692

Mit Java 8, Steves Antwort werden können

public void testMyFunction() throws Exception {
    Application mock = mock(Application.class);
    when(mock.myFunction(anyString())).thenAnswer(
    invocation -> {
        Object[] args = invocation.getArguments();
        return args[0];
    });

    assertEquals("someString", mock.myFunction("someString"));
    assertEquals("anotherString", mock.myFunction("anotherString"));
}

EDIT: Noch kürzer:

public void testMyFunction() throws Exception {
    Application mock = mock(Application.class);
    when(mock.myFunction(anyString())).thenAnswer(
        invocation -> invocation.getArgument(0));

    assertEquals("someString", mock.myFunction("someString"));
    assertEquals("anotherString", mock.myFunction("anotherString"));
}

42voto

migu Punkte 1331

Ich hatte ein sehr ähnliches Problem. Das Ziel war es, einen Dienst zu simulieren, der Objekte aufbewahrt und sie anhand ihres Namens zurückgeben kann. Der Dienst sieht wie folgt aus:

public class RoomService {
    public Room findByName(String roomName) {...}
    public void persist(Room room) {...}
}

Der Service Mock verwendet eine Karte, um die Room-Instanzen zu speichern.

RoomService roomService = mock(RoomService.class);
final Map<String, Room> roomMap = new HashMap<String, Room>();

// mock for method persist
doAnswer(new Answer<Void>() {
    @Override
    public Void answer(InvocationOnMock invocation) throws Throwable {
        Object[] arguments = invocation.getArguments();
        if (arguments != null && arguments.length > 0 && arguments[0] != null) {
            Room room = (Room) arguments[0];
            roomMap.put(room.getName(), room);
        }
        return null;
    }
}).when(roomService).persist(any(Room.class));

// mock for method findByName
when(roomService.findByName(anyString())).thenAnswer(new Answer<Room>() {
    @Override
    public Room answer(InvocationOnMock invocation) throws Throwable {
        Object[] arguments = invocation.getArguments();
        if (arguments != null && arguments.length > 0 && arguments[0] != null) {
            String key = (String) arguments[0];
            if (roomMap.containsKey(key)) {
                return roomMap.get(key);
            }
        }
        return null;
    }
});

Jetzt können wir unsere Tests mit dieser Attrappe durchführen. Zum Beispiel:

String name = "room";
Room room = new Room(name);
roomService.persist(room);
assertThat(roomService.findByName(name), equalTo(room));
assertNull(roomService.findByName("none"));

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