Hacer que un método simulado devuelva un argumento que se le pasó
Considere una firma de método como:
public String myFunction(String abc);
¿Puede Mockito ayudar a devolver la misma cadena que recibió el método?
Desde Mockito 1.9.5+ y Java 8+
Puedes usar una expresión lambda, como:
when(myMock.myFunction(anyString())).thenAnswer(i -> i.getArguments()[0]);
¿Dónde
i
hay una instancia deInvocationOnMock
.
Para versiones anteriores
Puedes crear una respuesta en Mockito. Supongamos que tenemos una interfaz llamada MyInterface con un método myFunction.
public interface MyInterface {
public String myFunction(String abc);
}
Aquí está el método de prueba con una respuesta Mockito:
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"));
}
Si tiene Mockito 1.9.5 o superior, hay un nuevo método estático que puede crear el Answer
objeto por usted. Necesitas escribir algo como
import static org.mockito.Mockito.when;
import static org.mockito.AdditionalAnswers.returnsFirstArg;
when(myMock.myFunction(anyString())).then(returnsFirstArg());
o alternativamente
doAnswer(returnsFirstArg()).when(myMock).myFunction(anyString());
Tenga en cuenta que el returnsFirstArg()
método es estático en la AdditionalAnswers
clase, lo cual es nuevo en Mockito 1.9.5; entonces necesitarás la importación estática correcta.
Con Java 8 es posible crear una respuesta de una línea incluso con una versión anterior de Mockito:
when(myMock.myFunction(anyString()).then(i -> i.getArgumentAt(0, String.class));
Por supuesto, esto no es tan útil como el uso AdditionalAnswers
sugerido por David Wallace, pero podría ser útil si desea transformar un argumento "sobre la marcha".
Con Java 8, la respuesta de Steve puede ser
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"));
}
EDITAR: Aún más corto:
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"));
}
Tuve un problema muy similar. El objetivo era burlarse de un servicio que persiste Objetos y puede devolverlos por su nombre. El servicio se ve así:
public class RoomService {
public Room findByName(String roomName) {...}
public void persist(Room room) {...}
}
El simulacro de servicio utiliza un mapa para almacenar las instancias de Room.
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;
}
});
Ahora podemos ejecutar nuestras pruebas en este simulacro. Por ejemplo:
String name = "room";
Room room = new Room(name);
roomService.persist(room);
assertThat(roomService.findByName(name), equalTo(room));
assertNull(roomService.findByName("none"));
Esta es una pregunta bastante antigua, pero creo que sigue siendo relevante. Además, la respuesta aceptada funciona solo para String. Mientras tanto, existe Mockito 2.1 y algunas importaciones han cambiado, así que me gustaría compartir mi respuesta actual:
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());
myClass.myFunction se vería así:
public class MyClass {
public ClassOfArgument myFunction(ClassOfArgument argument){
return argument;
}
}