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

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

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

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

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


}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.