Mockito weryfikuje kolejność / sekwencję wywołań metod

205

Czy istnieje sposób na sprawdzenie, czy a methodOnejest wywoływane wcześniej methodTwow 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
źródło

Odpowiedzi:

305

InOrder pomaga ci to zrobić.

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
źródło
5
Jest to poprawne, chociaż wezwania do do Nic nie są tutaj potrzebne, z wyjątkiem miejsca zastępczego dla innych kodów pośredniczących. Mockito domyślnie po cichu przyjmuje nieważne wywołania metod.
Jeff Bowman
1
Akceptuje je, podczas gdy obiekt nie ma zależności, jeśli obiekt ma zależności, będzie wyjątek =)
Koitoer
14
rozważ inOrder.verifyNoMoreInteractions();po ostatniej weryfikacji w tym przykładzie, aby sprawdzić, czy nie wykonano innych połączeń.
DwB
1
Wyjaśnij: Można bezpiecznie zdefiniować inOrder tuż przed weryfikacją - po wywołaniu niektórych (przetestowanych) metod na próbach.
user3078523,
Czy wyniki są takie same dla inOrder(firstMock, secondMock)i inOrder(secondMock, firstMock)? Być może możesz zaktualizować odpowiedź, aby zanotować tę notatkę.
kevinarpe
95

Zauważ, że możesz także użyć klasy InOrder, aby sprawdzić, czy różne metody są wywoływane po kolei na jednej próbce, a nie tylko na dwóch lub więcej próbkach.

Załóżmy, że mam dwie klasy Fooi Bar:

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

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

Mogę wtedy dodać klasę do testów, które Bar„s firstThenSecond()metoda faktycznie nazywa first(), a następnie second(), a nie second(), wtedy first(). Zobacz następujący kod testowy:

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
źródło
1
To powinien być komentarz do zaakceptowanej odpowiedzi, a nie zupełnie nowa odpowiedź.
ach
12
Nie zgadzam się z twoim komentarzem @ach Próbka kodu pomaga, więc nowa odpowiedź ma sens.
Snekse
2
Czy istnieje sposób na sprawdzenie, czy ta sama metoda jest wywoływana dwukrotnie, ale weryfikacja kolejności przekazywanych parametrów? np pierwsze find('foo'), a następniefind('bar')
Snekse
1
Wygląda na to, że to może być moja odpowiedź stackoverflow.com/questions/36573399/…
Snekse
3
To jest rzeczywiście lepszy przykład niż zaakceptowana odpowiedź, ponieważ pokazuje bardziej typowe użycie niżdoNothing()
Archimedes Trajano
37

Tak, jest to opisane w dokumentacji. Musisz użyć klasy InOrder .

Przykład (przy założeniu, że utworzono już dwie próby):

InOrder inOrder = inOrder(serviceAMock, serviceBMock);

inOrder.verify(serviceAMock).methodOne();
inOrder.verify(serviceBMock).methodTwo();
LaurentG
źródło
1

W przypadku BDD jest to możliwe

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


}
Tracki
źródło