Формирование Мокито "грамматики"

Mockito выглядит как довольно приятный фреймворк для Java. Единственная проблема в том, что я не могу найти какую-либо конкретную документацию о лучших способах использования их API. Общие методы, используемые в тестах, включают в себя:

doXXX(???) : Stubber
when(T) : OngoingStubbing
then(T) : OngoingStubbing
verify(???) : T
given(T) : BDDOngoingStubbing
willXXX(???) : BDDStubber

Когда вы видите на практике примеры Mockito, вы видите такой код:

when(yourMethod()).thenReturn(5);

Из всех документов, которые я прочитал, я определил несколько "шаблонов" "грамматик" Мокито, полученных из последовательных вызовов этих методов вместе, как в примере выше. Некоторые общие шаблоны, которые я нашел:

Когда / Тогда: когда (yourMethod()). ThenReturn (5);

Given / Will: данный (yourMethod()). WillThrow (OutOfMemoryException.class);

Do / When: doReturn (7).when (yourMock.fizzBuzz ());

Will / Given / Do: willReturn (any ()). Данное (yourMethod()). DoNothing ();

Verify / Do: verify (yourMethod()). DoThrow(SomeException.class);

Я задыхаюсь, как правильно выбрать шаблон / комбинацию вызовов методов для моделирования моих тестовых случаев. Похоже, что вы можете объединить их в последовательные, казалось бы, бесконечные комбинации, и я не уверен, какой шаблон подходит для какой проблемы.

Может ли какой-нибудь гуру Мокито помочь пролить свет на то, какие шаблоны / комбинации методов Мокито используются для каких типов тестовых случаев (и почему)? Заранее спасибо!

3 ответа

Решение

У Mockito часто есть несколько способов делать вещи.

Я использую в основном:

// Setup expectations
when(object.method()).thenReturn(value);
when(object.method()).thenThrow(exception);
doThrow(exception).when(object.voidMethod());


// verify things
verify(object, times(2)).method();
verify(object, times(1)).voidMethod();

Я обнаружил, что с этими тремя видами звонков я могу делать 95% того, что мне нужно.

Кроме того, какую версию Mockito вы используете? конструкции "данный" и "будет" отсутствуют в последней версии (1.9.0+)

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

public class ReturnFirstArg<T> implements Answer<T> {
    public T answer(InvocationOnMock invocation) {
        return invocation.getArguments()[0];
    }
}

when(object.method(7)).thenAnswer(new ReturnFirstArg<Integer>());

Есть несколько недостатков when/thenReturn, when/thenThrow а также when/then Синтаксисы. Например,

  • В случае when/thenReturn, если возвращаемый тип является универсальным с подстановочным знаком, и вы хотите вернуть макет того же типа, вы не сможете избежать предупреждения компиляции.
  • Вы не можете использовать when/thenThrow а также when/then для пустого метода.
  • Вы не можете использовать эти синтаксисы на шпионах Мокито.
  • Вы можете только позвонить when один раз для каждой комбинации фиктивного объекта, метода и аргументов, если вы не вызываете reset на макете.
  • призвание when Несколько раз для одной комбинации фиктивного объекта и метода, когда вы используете сопоставители аргументов, может возникнуть проблема.

Мне трудно запомнить эти случаи. Поэтому вместо того, чтобы пытаться отслеживать, когда when/thenReturn, when/thenThrow а также when/then Синтаксисы будут и не будут работать, я предпочитаю избегать их полностью, в пользу doReturn/when, doThrow/when а также doAnswer/when альтернативы. То есть, так как вам иногда нужно doReturn/when, doThrow/when а также doAnswer/when, и вы можете ВСЕГДА использовать эти методы, нет смысла учиться использовать when/thenReturn, when/thenThrow а также when/then,

Обратите внимание, что doReturn, doThrow а также doAnswer могут быть соединены вместе так же, как thenReturn, thenThrow а также then, Чего у них нет, так это возможности вернуть несколько значений (или выдать несколько исключений, или выполнить несколько ответов) в течение одного вызова doReturn, doThrow а также doAnswer, Но я нахожу, что мне нужно делать это так редко, что это на самом деле не имеет значения.

Есть еще один недостаток doReturn, который я считаю незначительным. Вы не получаете проверку времени компиляции типа его аргумента, как вы делаете с when/thenReturn, Поэтому, если вы ошиблись в типе аргумента, вы не узнаете, пока не запустите свой тест. Честно говоря, мне все равно.

Таким образом, я использую Mockito более двух лет, и я считаю, что doReturn, doThrow а также doAnswer быть лучшей практикой Мокито. Другие пользователи Mockito не согласны.

На самом деле все выглядит намного проще, чем вы думали

REF: http://static.javadoc.io/org.mockito/mockito-core/2.7.12/org/mockito/Mockito.html

Проверить:

Чтобы использовать Mockito, вам необходимо понять одну базовую философию Mockito: "Окурки и проверки" разделены. Поэтому упомянутое вами "Подтверждение / Выполнение" фактически выполняет задание "Подтверждение", а остальные 4 "грамматики" предназначены для заглушки. Заглушки определяют, как макет объекта будет реагировать в другой ситуации. Проверка заключается в том, чтобы удостовериться, что макеты вызываются, как и ожидалось, при предыдущем вызове тестируемой системы (SUT).

Когда / Затем, Дано / Будет:

Затем речь идет о семьях "Когда" и "Дано". Вы можете просто рассматривать их как псевдонимы друг друга. "Данное" семейство добавлено в Mockito 1.8.x, чтобы оно выглядело более согласованным с практиками BDD.

DoXxx:

В нормальном случае мы в основном используем when(xxx).then(...) (а также given(...).will(...)) Однако в некоторых случаях синтаксис не работает. Наиболее очевидный случай, когда возвращаемый тип метода-заглушки имеет тип void. В таком случае when(mockObj.voidMethod()).thenThrow(anException) не собирается компилировать. В качестве обходного пути создается альтернативный синтаксис Do/When, поэтому вы можете написать предыдущую строку как doThrow(anException).when(mockObj.voidMethod())

Другие вопросы по тегам