Моделювати перший виклик не вдається, другий дзвінок успішний


119

Я хочу використовувати Mockito для тестування (спрощеного) коду нижче. Я не знаю, як сказати Мокіто першому невдачі, потім вдруге.

for(int i = 1; i < 3; i++) {
  String ret = myMock.doTheCall();

  if("Success".equals(ret)) {
    log.write("success");
  } else if ( i < 3 ) {
    log.write("failed, but I'll try again. attempt: " + i);
  } else {
    throw new FailedThreeTimesException();
  }
}

Я можу встановити тест успішності за допомогою:

Mockito.when(myMock).doTheCall().thenReturn("Success");

І тест на відмову:

Mockito.when(myMock).doTheCall().thenReturn("you failed");

Але як я можу перевірити, що якщо це не вдалося один раз (або два рази), то це вдасться?

Відповіді:


250

З документів :

Іноді нам потрібно заглушити різне значення / виняток для одного виклику методу. Типовим випадком використання може бути глузування з ітераторів. Оригінальна версія Mockito не мала цієї функції для просування простого глузування. Наприклад, замість ітераторів можна використовувати колекції Iterable або просто колекції. Вони пропонують природні способи заглушки (наприклад, використання реальних колекцій). У рідкісних сценаріях може бути корисним заклик послідовних дзвінків:

when(mock.someMethod("some arg"))
   .thenThrow(new RuntimeException())
  .thenReturn("foo");

//First call: throws runtime exception:
mock.someMethod("some arg");

//Second call: prints "foo"
System.out.println(mock.someMethod("some arg"));

Тож у вашому випадку ви хочете:

when(myMock.doTheCall())
   .thenReturn("You failed")
   .thenReturn("Success");

25
Це вказувало мені в правильному напрямку (спасибі) за мій сценарій, що doThrow(new RuntimeException()).doNothing().when(myMock).doTheCall();
стосувався

38

Найкоротший спосіб написати те, що ти хочеш

when(myMock.doTheCall()).thenReturn("Success", "you failed");

Коли ви подаєте неодноразові аргументи, thenReturnяк це, кожен аргумент буде використаний не більше одного разу, за винятком самого останнього аргументу, який використовується стільки разів, скільки потрібно. Наприклад, у цьому випадку, якщо ви здійсните дзвінок 4 рази, ви отримаєте "Успіх", "Ви не вдалися", "Ви не вдалися", "Ви не вдалися".


22

Оскільки коментар, що стосується цього, важко прочитати, я додам відповідь відформатовану.

Якщо ви намагаєтеся зробити це за допомогою voidфункції, яка просто кидає виняток, після чого слід діяти без кроку поведінки, тоді ви зробите щось подібне:

Mockito.doThrow(new Exception("MESSAGE"))
            .doNothing()
            .when(mockService).method(eq());

4

Щоб доповнити цю і цю відповідь, ви також можете скористатися циклом для ланцюжка знущаються дзвінків. Це корисно, якщо вам потрібно знущатися над однією і тією ж справою кілька разів або знущатися над якоюсь схемою.

Напр. (Хоч і надуманий):

import org.mockito.stubbing.Stubber;

Stubber stubber = doThrow(new Exception("Exception!"));
for (int i=0; i<10; i++) {
    if (i%2 == 0) {
        stubber.doNothing();
    } else {
        stubber.doThrow(new Exception("Exception"));
    }
}
stubber.when(myMockObject).someMethod(anyString());

Я насправді не знав про цього Стуббера і вважав його корисним +1.
Михай Морцов

Це має бути правильною відповіддю, якщо вам потрібен метод виклику анулювання.
db80

4

У мене інша ситуація, я хотів знущатися над voidфункцією першого дзвінка і виконувати її нормально під час другого дзвінка.

Це працює для мене:

Mockito.doThrow(new RuntimeException("random runtime exception"))
       .doCallRealMethod()
       .when(spy).someMethod(Mockito.any());
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.