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

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

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

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

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


}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.