Pregunta

Como burlarse de métodos con el tipo de retorno vacío?

He implementado un patrón de observador pero no puedo burlarse con Mockito porque no sé cómo.

Y he intentado encontrar un ejemplo en Internet, pero no tuvo éxito.

Mi clase es el siguiente:

public class World {

    List<Listener> listeners;

    void addListener(Listener item) {
        listeners.add(item);
    }

    void doAction(Action goal,Object obj) {
        setState("i received");
        goal.doAction(obj);
        setState("i finished");
    }

    private string state;
    //setter getter state
} 

public class WorldTest implements Listener {

    @Test public void word{
    World  w= mock(World.class);
    w.addListener(this);
    ...
    ...

    }
}

interface Listener {
    void doAction();
}

El sistema no se activan con la maqueta. = ( Quiero mostrar el estado del sistema anterior mencionada. Y hacer la afirmación según ellos.

¿Fue útil?

Solución 4

La solución de llamado problema es utilizar un spy Mockito.spy (...) en lugar de un mock Mockito.mock (..) .

Spy nos permite burla parcial. Mockito es bueno en esta materia. Debido a que tiene la clase que no es completa, de esta manera se burla de algún lugar requerido en esta clase.

Otros consejos

Tome un vistazo a la Mockito documentación de la API . A medida que el documento vinculado menciona (punto # 12), puede utilizar cualquiera de los doThrow(), doAnswer(), doNothing(), familia doReturn() de métodos de marco Mockito burlarse métodos vacíos.

Por ejemplo,

Mockito.doThrow(new Exception()).when(instance).methodName();

o si quieres combinarlo con el comportamiento de seguimiento,

Mockito.doThrow(new Exception()).doNothing().when(instance).methodName();

Suponiendo que usted está buscando en burlarse del setState(String s) colocador en el Mundial de la clase a continuación es el código utiliza el método doAnswer burlarse de la setState.

World  mockWorld = mock(World.class); 
doAnswer(new Answer<Void>() {
    public Void answer(InvocationOnMock invocation) {
      Object[] args = invocation.getArguments();
      System.out.println("called with arguments: " + Arrays.toString(args));
      return null;
    }
}).when(mockWorld).setState(anyString());

Creo que he encontrado una respuesta simple a esa pregunta, para llamar al método real para un solo método (incluso si no tiene un retorno void) se puede hacer esto:

Mockito.doCallRealMethod().when(<objectInstance>).<method>();
<objectInstance>.<method>();

O bien, puede llamar al método real para todos los métodos de esa clase, hacer esto:

<Object> <objectInstance> = mock(<Object>.class, Mockito.CALLS_REAL_METHODS);

Agregando a lo @sateesh Dicho esto, cuando lo que desea es burlarse de un método de vacío con el fin de evitar que la prueba de llamar a él, se puede utilizar un Spy de esta manera:

World world = new World();
World spy = Mockito.spy(world);
Mockito.doNothing().when(spy).methodToMock();

Cuando se desea ejecutar la prueba, asegúrese de llamar al método de prueba en el objeto spy y no en el objeto world. Por ejemplo:

assertEquals(0,spy.methodToTestThatShouldReturnZero());

En primer lugar: siempre se debe importar Mockito estática, de esta manera el código será mucho más fácil de leer (e intuitivo):

import static org.mockito.Mockito.*;

Para burlona parcial y manteniendo la funcionalidad original en el resto ofertas Mockito "espía".

Se puede utilizar de la siguiente manera:

private World world = spy(World.class);

Para eliminar un método de ser ejecutado podría utilizar algo como esto:

doNothing().when(someObject).someMethod(anyObject());

para dar un comportamiento personalizado a un método de uso "cuando" con un "thenReturn":

doReturn("something").when(this.world).someMethod(anyObject());

Para más ejemplos por favor, encontrar las muestras Mockito en el doc.

¿Cómo burlarse métodos vacíos en los Mockito - hay dos opciones:

  1. doAnswer -. Si queremos que nuestro método vacío burlado de hacer algo (burlarse del comportamiento a pesar de ser void)
  2. doThrow -. Luego está Mockito.doThrow() si desea lanzar una excepción a partir del método vacío burlado

A continuación se presenta un ejemplo de cómo usarlo (no es un caso de uso ideal, pero sólo quería ilustrar el uso básico).

@Test
public void testUpdate() {

    doAnswer(new Answer<Void>() {

        @Override
        public Void answer(InvocationOnMock invocation) throws Throwable {
            Object[] arguments = invocation.getArguments();
            if (arguments != null && arguments.length > 1 && arguments[0] != null && arguments[1] != null) {

                Customer customer = (Customer) arguments[0];
                String email = (String) arguments[1];
                customer.setEmail(email);

            }
            return null;
        }
    }).when(daoMock).updateEmail(any(Customer.class), any(String.class));

    // calling the method under test
    Customer customer = service.changeEmail("old@test.com", "new@test.com");

    //some asserts
    assertThat(customer, is(notNullValue()));
    assertThat(customer.getEmail(), is(equalTo("new@test.com")));

}

@Test(expected = RuntimeException.class)
public void testUpdate_throwsException() {

    doThrow(RuntimeException.class).when(daoMock).updateEmail(any(Customer.class), any(String.class));

    // calling the method under test
    Customer customer = service.changeEmail("old@test.com", "new@test.com");

}
}

Se puede encontrar más detalles sobre cómo simulacro y prueba void métodos con Mockito en mi post Cómo burlarse con Mockito (Una guía completa con ejemplos)

La adición de otra respuesta a la racimo (sin doble sentido) ...

Sí es necesario llamar al método doAnswer si no puede \ no quieren usar espionaje. Sin embargo, no necesariamente tienen que rodar su propia Respuesta . Hay varias implementaciones por defecto. En particular, CallsRealMethods .

En la práctica, se ve algo como esto:

doAnswer(new CallsRealMethods()).when(mock)
        .voidMethod(any(SomeParamClass.class));

O:

doAnswer(Answers.CALLS_REAL_METHODS.get()).when(mock)
        .voidMethod(any(SomeParamClass.class));

En Java 8 esto se puede hacer un poco más limpio, suponiendo que tiene una importación estática para org.mockito.Mockito.doAnswer:

doAnswer(i -> {
  // Do stuff with i.getArguments() here
  return null;
}).when(*mock*).*method*(*methodArguments*);

El return null; es importante y sin ella la compilación fallará con algunos errores bastante oscuros, ya que no será capaz de encontrar un reemplazo adecuado para doAnswer.

Por ejemplo, un ExecutorService que solo se ejecuta inmediatamente cualquier Runnable pasado a execute() podría ser implementado usando:

doAnswer(i -> {
  ((Runnable) i.getArguments()[0]).run();
  return null;
}).when(executor).execute(any());

Creo que sus problemas se deben a la estructura de la prueba. He encontrado que es difícil de mezclar burlarse con el método tradicional de la implementación de interfaces en la clase de prueba (como se ha hecho aquí).

Si implementa el oyente como una maqueta a continuación, puede verificar la interacción.

Listener listener = mock(Listener.class);
w.addListener(listener);
world.doAction(..);
verify(listener).doAction();

Esto debe satisfacer que el 'mundo' está haciendo lo correcto.

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