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

Ответы:


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

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

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

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


}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.