Considérese una firma de método como:¿Cómo puedo hacer que un método devuelva un argumento que se le pasó?
public String myFunction(String abc);
Puede Mockito ayudar a devolver la misma cadena que el método recibido?
Considérese una firma de método como:¿Cómo puedo hacer que un método devuelva un argumento que se le pasó?
public String myFunction(String abc);
Puede Mockito ayudar a devolver la misma cadena que el método recibido?
Puede 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í es el método de ensayo 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 hay una manera aún más fácil mediante el uso de las funciones lambda:
when(myMock.myFunction(anyString())).thenAnswer(i -> i.getArguments()[0]);
Esto es lo que estaba buscando, también. ¡Gracias! Mi problema era diferente, sin embargo. Quiero simular un servicio de persistencia (EJB) que almacena objetos y los devuelve por nombre. – migu
Genial, me ahorró mucho tiempo también – Mat
Creo que debería haber una manera más simple usando la captura de argumentos o algo ... – iwein
Uso algo similar (básicamente es el mismo enfoque). Algunas veces es útil tener una salida predefinida de retorno de objeto simulada para ciertas entradas. Esto es 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
}
}
}
);
Tuve un problema muy similar. El objetivo era burlarse de un servicio que persiste en los 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 la habitación.
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"));
Si tiene Mockito 1.9.5 o superior, hay un nuevo método estático que puede hacer que el objeto Answer
para usted. Usted tiene que escribir algo así como
when(myMock.myFunction(anyString())).then(returnsFirstArg());
o alternativamente
doAnswer(returnsFirstArg()).when(myMock).myFunction(anyString());
Tenga en cuenta que el método returnsFirstArg()
es estático en la clase AdditionalAnswers
, que es nuevo para Mockito 1.9.5; por lo que necesitarás la importación estática correcta.
revisando todas las respuestas este 1 es lo mejor ... no sé por qué no es aceptado 1 – Nimrod007
Tal vez porque la respuesta aceptada es anterior a Mockito 1.9.5 – Jay
Nota: es 'cuando (...). luego (returnsFirstArg())', equivocadamente tuve ' when (...). thenReturn (returnsFirstArg()) 'que dio' java.lang.ClassCastException: org.mockito.internal.stubbing.answers.ReturnsArgumentAt no se puede convertir a ' –
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 de AdditionalAnswers
sugerido por David Wallace, pero podría ser útil si quieres transformar el argumento "sobre la marcha".
Brillante. Gracias. Si el argumento es 'largo', ¿esto todavía puede funcionar con boxeo y' Long.class'? – vikingsteve
Con Java 8, Steve's answer puede convertirse en
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: 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"));
}
Aún más corto^_^ '' when (mock.myFunction (anyString())). ThenAnswer (invocación -> invocation.getArgument (0)); '' –
Ha fantástico. Editado para reflejar esto ^ – yiwei
Es posible que desee utilizar verificar() en combinación con el ArgumentCaptor para asegurar la ejecución de la prueba y el 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 argumento ' El valor de s es obviamente accesible a través del argument.getValue() para una mayor manipulación/verificación/lo que sea.
Bien, ¿qué hay de cualquier marco de burlarse de Java en general ... ¿Es esto posible con cualquier otro marco, o debería simplemente crear un stub tonto para imitar el comportamiento que quiero? –