Mockito verifica el orden / secuencia de llamadas a métodos

205

¿Hay alguna forma de verificar si methodOnese llama antes methodTwoa Mockito?

public class ServiceClassA {
    public void methodOne(){}
 }

public class ServiceClassB {
    public void methodTwo(){}
 }

public class TestClass {
    public void method(){
        ServiceClassA serviceA = new ServiceClassA();
        ServiceClassB serviceB = new ServiceClassB();
        serviceA.methodOne();
        serviceB.methodTwo();
    }
}
froi
fuente

Respuestas:

305

InOrder te ayuda a hacer eso.

ServiceClassA firstMock = mock(ServiceClassA.class);
ServiceClassB secondMock = mock(ServiceClassB.class);

Mockito.doNothing().when(firstMock).methodOne();   
Mockito.doNothing().when(secondMock).methodTwo();  

//create inOrder object passing any mocks that need to be verified in order
InOrder inOrder = inOrder(firstMock, secondMock);

//following will make sure that firstMock was called before secondMock
inOrder.verify(firstMock).methodOne();
inOrder.verify(secondMock).methodTwo();
Koitoer
fuente
55
Esto es correcto, aunque las llamadas a hacerNada no son necesarias aquí, excepto como marcador de posición para otro stubbing. Mockito aceptará silenciosamente las llamadas al método nulo por defecto.
Jeff Bowman
1
Los acepta mientras el objeto no tenga dependencias si el objeto tiene dependencias habrá una excepción =)
Koitoer
14
considere inOrder.verifyNoMoreInteractions();después de la última verificación en este ejemplo para verificar que no se realizaron otras llamadas.
DwB
1
Solo para aclarar: es seguro definir inOrder justo antes de verificar, después de invocar algunos métodos (probados) en simulacros.
user3078523
¿Son los resultados iguales para inOrder(firstMock, secondMock)y inOrder(secondMock, firstMock)? Quizás pueda actualizar la respuesta para hacer una nota al respecto.
kevinarpe
95

Tenga en cuenta que también puede usar la clase InOrder para verificar que varios métodos se invocan en orden en un simulacro único, no solo en dos o más simulacros.

Supongamos que tengo dos clases Fooy Bar:

public class Foo {
  public void first() {}
  public void second() {}
}

public class Bar {
  public void firstThenSecond(Foo foo) {
    foo.first();
    foo.second();
  }
}

Entonces puedo agregar una clase de prueba para probar que Barel firstThenSecond()método realmente llama first(), entonces second(), y no second(), entonces first(). Vea el siguiente código de prueba:

public class BarTest {
  @Test
  public void testFirstThenSecond() {
    Bar bar = new Bar();
    Foo mockFoo = Mockito.mock(Foo.class);
    bar.firstThenSecond(mockFoo);

    InOrder orderVerifier = Mockito.inOrder(mockFoo);
    // These lines will PASS
    orderVerifier.verify(mockFoo).first();
    orderVerifier.verify(mockFoo).second();

    // These lines will FAIL
    // orderVerifier.verify(mockFoo).second();
    // orderVerifier.verify(mockFoo).first();
  }
}
entpnerd
fuente
1
Esto debería haber sido un comentario sobre la respuesta aceptada, no una respuesta completamente nueva.
ach
12
No estoy de acuerdo con tu comentario @ach El código de muestra ayuda, por lo que una nueva respuesta tiene sentido.
Snekse
2
¿Hay alguna forma de verificar que el mismo método se llama dos veces, pero verifica el orden de los parámetros que se pasan? ej. Primero find('foo'), luegofind('bar')
Snekse
1
Parece que esta podría ser mi respuesta stackoverflow.com/questions/36573399/…
Snekse
3
Este es en realidad un mejor ejemplo que la respuesta aceptada porque muestra un uso más típico quedoNothing()
Arquímedes Trajano
37

Sí, esto se describe en la documentación. Tienes que usar la clase InOrder .

Ejemplo (suponiendo dos simulacros ya creados):

InOrder inOrder = inOrder(serviceAMock, serviceBMock);

inOrder.verify(serviceAMock).methodOne();
inOrder.verify(serviceBMock).methodTwo();
LaurentG
fuente
1

Con BDD es

@Test
public void testOrderWithBDD() {


    // Given
    ServiceClassA firstMock = mock(ServiceClassA.class);
    ServiceClassB secondMock = mock(ServiceClassB.class);

    //create inOrder object passing any mocks that need to be verified in order
    InOrder inOrder = inOrder(firstMock, secondMock);

    willDoNothing().given(firstMock).methodOne();
    willDoNothing().given(secondMock).methodTwo();

    // When
    firstMock.methodOne();
    secondMock.methodTwo();

    // Then
    then(firstMock).should(inOrder).methodOne();
    then(secondMock).should(inOrder).methodTwo();


}
Tracio
fuente