Mockito проверяет порядок / последовательность вызовов методов

205

Есть ли способ проверить, methodOneвызывается ли ранее methodTwoв 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
источник

Ответы:

305

InOrder поможет вам сделать это.

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
источник
5
Это правильно, хотя вызовы doNothing здесь не нужны, кроме как в качестве заполнителя для другой заглушки. По умолчанию Mockito будет молча принимать вызовы void.
Джефф Боуман
1
Он принимает их, пока у объекта нет зависимостей, если у объекта есть зависимости, будет исключение =)
Koitoer
14
рассмотрим inOrder.verifyNoMoreInteractions();после последней проверки в этом примере, чтобы убедиться, что не было сделано никаких других вызовов.
DwB
1
Просто для пояснения: можно безопасно определить inOrder непосредственно перед проверкой - после вызова некоторых (проверенных) методов для макетов.
user3078523
Одинаковы ли результаты для inOrder(firstMock, secondMock)и inOrder(secondMock, firstMock)? Возможно, вы можете обновить ответ, чтобы сделать пометку об этом.
Кевинарпе
95

Обратите внимание, что вы также можете использовать класс InOrder для проверки того, что различные методы вызываются по порядку на одном макете, а не только на двух или более.

Предположим, у меня есть два класса Fooи Bar:

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

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

То я могу добавить тестовый класс тест , который Bar«S firstThenSecond()метод фактически вызывает first(), то second()и не second(), тогда first(). Смотрите следующий тестовый код:

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
источник
1
Это должен был быть комментарий к принятому ответу, а не новый ответ.
ACH
12
Я не согласен с вашим комментарием @ach. Пример кода помогает, поэтому новый ответ имеет смысл.
Снексе
2
Есть ли способ убедиться, что один и тот же метод вызывается дважды, но проверить порядок передаваемых параметров? напр. сначала find('foo'), потомfind('bar')
Снексе
1
Похоже, что это может быть мой ответ stackoverflow.com/questions/36573399/…
Снексе
3
Это на самом деле лучший пример, чем принятый ответ, потому что он показывает более типичное использование, чемdoNothing()
Архимед Траяно
37

Да, это описано в документации. Вы должны использовать класс InOrder .

Пример (при условии, что два макета уже созданы):

InOrder inOrder = inOrder(serviceAMock, serviceBMock);

inOrder.verify(serviceAMock).methodOne();
inOrder.verify(serviceBMock).methodTwo();
LaurentG
источник
1

С BDD это

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


}
фракийский
источник