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.