es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo simular según el número de invocaciones de un método utilizando Java y Mockito?

Tengo un método que devuelve la cantidad de filas de algo como un registro de actividades.

Así que si lo llamo por primera vez, devuelve 0 filas. Pero si lo llamo una vez más, podría devolver una o más filas.

someList = getLogLines("unique-id");

Otro método tiene una lógica relacionada con la cantidad de filas del primer método.

initialRows = getLogLines("unique-id");
if (initialRows.size() == 0) {
  // alguna lógica
}
// otras líneas y lógica
newRows = getLogLines("unique-id");
if (newRows.size() > 0) {
  // otra lógica
}

Como puedes ver, se llama a getLogLines("unique-id") varias veces con el mismo argumento.

En las pruebas unitarias, ¿cómo puedo simular getLogLines para recibir un resultado según el número de invocaciones con el mismo argumento?

Si cada invocación tuviera argumentos diferentes, sería fácil simularlo.

doReturn(emptyRows).when(Foo).getLogLines("bar-id");
doReturn(severalRows).when(Foo).getLogLines("baz-id");

Pero no encuentro cómo simular un resultado diferente cuando el argumento es el mismo.

Solo encontré Mockito.times(x), pero no encuentro cómo combinar verify y doReturn:

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para simular el método getLogLines y devolver resultados diferentes según el número de veces que se llame con el mismo argumento, podemos usar una combinación de Answer y AtomicInteger de Mockito.

    Aquí tienes un ejemplo de cómo se puede hacer:

    import org.mockito.stubbing.Answer;
    import static org.mockito.Mockito.*;
    
    @Test
    public void testGetLogLines() {
        // Crea un mock de la clase que tiene el método getLogLines
        MyClass myClassMock = mock(MyClass.class);
    
        // Crea un AtomicInteger para realizar un seguimiento del número de invocaciones
        AtomicInteger invocationCount = new AtomicInteger(0);
    
        // Configura el mock para devolver resultados diferentes según el número de invocaciones
        when(myClassMock.getLogLines("unique-id")).thenAnswer(new Answer<><string>>() {
            @Override
            public List<string> answer(InvocationOnMock invocation) throws Throwable {
                int count = invocationCount.getAndIncrement();
                if (count == 0) {
                    return Collections.emptyList();  // Devuelve una lista vacía para la primera invocación
                } else {
                    return Arrays.asList("fila1", "fila2");  // Devuelve dos filas para las invocaciones siguientes
                }
            }
        });
    
        // Llama al método de lógica que utiliza el método getLogLines
        List<string> filasIniciales = myClassMock.getLogLines("unique-id");
        if(filasIniciales.size()==0){
            // alguna lógica
        }
        List<string> nuevasFilas = myClassMock.getLogLines("unique-id");
        if(nuevasFilas.size()>0){
            // otra lógica
        }
    
        // Verifica que el método getLogLines fue llamado dos veces con el mismo argumento
        verify(myClassMock, times(2)).getLogLines("unique-id");
    }
    

    En este ejemplo, estamos utilizando un AtomicInteger llamado invocationCount para realizar un seguimiento del número de veces que se llama a getLogLines con el mismo argumento. Utilizamos esta cuenta para determinar qué resultado devolver.

    En el método thenAnswer, estamos devolviendo una lista vacía para la primera invocación y una lista con dos filas para las invocaciones siguientes.

    Finalmente, verificamos que el método getLogLines se haya llamado dos veces con el mismo argumento utilizando verify y times.

Comments are closed.