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?
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?
Respuestas:
Puedes crear una respuesta en Mockito. Supongamos que tenemos una interfaz llamada Aplicación con un método myFunction.
public interface Application {
public String myFunction(String abc);
}
Aquí está el método de prueba con una respuesta Mockito:
public void testMyFunction() throws Exception {
Application mock = mock(Application.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"));
}
Desde Mockito 1.9.5 y Java 8, también puede usar una expresión lambda:
when(myMock.myFunction(anyString())).thenAnswer(i -> i.getArguments()[0]);
when(...).then(Return.firstParameter())
when(foo(any()).then(i -> i.getArgumentAt(0, Bar.class))
. Y también puede usar una referencia de método y llamar a un método real.
Iterator<? extends ClassName>
que causa todo tipo de problemas de conversión en una thenReturn()
declaración.
when(foo(any()).thenAnswer(i -> i.getArguments()[0])
Si tiene Mockito 1.9.5 o superior, hay un nuevo método estático que puede hacer 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, que es nuevo en Mockito 1.9.5; entonces necesitará la importación estática correcta.
when(...).then(returnsFirstArg())
, erróneamente tuve lo when(...).thenReturn(returnsFirstArg())
que diojava.lang.ClassCastException: org.mockito.internal.stubbing.answers.ReturnsArgumentAt cannot be cast to
static org.mockito.AdditionalAnswers.returnsFirstArg
. esto para usar returnFirstArg. Además, puedo hacerlo when(myMock.myFunction(any())).then(returnsFirstArg())
en Mockito 2.20. *
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 el argumento "sobre la marcha".
long
, ¿esto todavía puede funcionar con el boxeo y Long.class
?
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"));
Con Java 8, la respuesta de Steve puede convertirse
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"));
}
Esta es una pregunta bastante antigua, pero creo que sigue siendo relevante. Además, la respuesta aceptada solo funciona para String. Mientras tanto, hay 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());
La función myClass.myFunction se vería así:
public class MyClass {
public ClassOfArgument myFunction(ClassOfArgument argument){
return argument;
}
}
Yo uso algo similar (básicamente es el mismo enfoque). A veces es útil que un objeto simulado devuelva resultados predefinidos para ciertas entradas. Eso va así:
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
}
}
}
);
Es posible que desee utilizar verificar () en combinación con ArgumentCaptor para asegurar la ejecución en la prueba y ArgumentCaptor para evaluar los argumentos:
ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
verify(mock).myFunction(argument.capture());
assertEquals("the expected value here", argument.getValue());
El valor del argumento es obviamente accesible a través del argumento.getValue () para una mayor manipulación / verificación / lo que sea.
Esto es un poco viejo, pero vine aquí porque tuve el mismo problema. Estoy usando JUnit pero esta vez en una aplicación Kotlin con mockk. Estoy publicando una muestra aquí para referencia y comparación con la contraparte de Java:
@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"))
}
Puede lograr esto usando ArgumentCaptor
Imagine que tiene la función de frijol así.
public interface Application {
public String myFunction(String abc);
}
Luego, en tu clase de prueba:
//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.
}
});
O si eres fanático de lambda simplemente haz:
//Use ArgumentCaptor to capture the value
ArgumentCaptor<String> param = ArgumentCaptor.forClass(String.class);
when(mock.myFunction(param.capture()))
.thenAnswer((invocation) -> param.getValue());
Resumen: utilice argumentocaptor, para capturar el parámetro pasado. Más tarde en respuesta, devuelva el valor capturado usando getValue
This doesn´t work (anymore?).
que tengo esto trabajando en mi instancia. 2. Lo siento, no tengo claro el punto que intentas hacer. La respuesta es específica a la pregunta de OP.