Pregunta

Considere una firma de método como:

public String myFunction(String abc);

Can Mockito ayudar a devolver la misma cadena que el método recibido?

¿Fue útil?

Solución

Se puede crear una respuesta en Mockito. Vamos a suponer, tenemos una interfaz denominada Aplicación con un myFunction método.

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

Aquí está 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]);

Otros consejos

Si usted 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

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 método returnsFirstArg() es estático en la clase AdditionalAnswers, que es nuevo para Mockito 1.9.5; por lo que tendrá la importación estática derecha.

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 se desea transformar argumento "sobre la marcha".

He tenido un problema muy similar. El objetivo era burlarse de un servicio que persiste objetos y les puede devolver por su nombre. Las miradas servicio como este:

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 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"));

Con Java 8, de Steve respuesta 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"));
}

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"));
}

Yo uso algo similar (que básicamente es el mismo enfoque). A veces es útil tener una salida simulada de retorno objeto predefinido para ciertos insumos. Que dice 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
               }
           }
       }
       );

Esta es una pregunta bastante viejo, pero creo que sigue siendo relevante. También la respuesta aceptada sólo funciona para las cuerdas. Mientras tanto hay Mockito 2.1 y algunas importaciones han cambiado, por lo 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());

El myClass.myFunction se vería así:

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

Es posible que desee utilizar verificar () en combinación con el ArgumentCaptor para asegurar la ejecución de la prueba y la 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 de la argument.getValue () para su posterior manipulación / verificación / lo que sea.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top