Mockito - разница между doReturn() и когда()

В настоящее время я использую Mockito для подделки объектов уровня сервиса в приложении Spring MVC, в котором я хочу протестировать мои методы контроллера. Однако, поскольку я читал о специфике Mockito, я обнаружил, что методы doReturn(...).when(...) эквивалентны when(...).thenReturn(...). Итак, мой вопрос заключается в том, что нужно иметь два метода, которые делают одно и то же, или то, что является тонкой разницей между doReturn(...).when(...) и when(...).thenReturn(...)?

Любая помощь будет оценена.

Ответ 1

Два синтаксиса для stubbing примерно эквивалентны. Однако вы всегда можете использовать doReturn/when для stubbing; но есть случаи, когда вы не можете использовать when/thenReturn. Одним из таких методов является stubbing void. Другие включают использование с шпионами Mockito и однократное выполнение одного и того же метода.

Одна вещь, которую when/thenReturn дает вам, что doReturn/when не выполняет проверку типов возвращаемого значения во время компиляции. Тем не менее, я считаю, что это почти не имеет значения - если у вас неправильный тип, вы узнаете, как только вы запустите тест.

Я настоятельно рекомендую использовать только doReturn/when. Нет смысла изучать два синтаксиса, когда они будут делать.

Вы можете сослаться на мой ответ в Формирование Mockito "grammars" - более подробный ответ на очень близкий вопрос.

Ответ 2

Оба подхода ведут себя по-разному, если вы используете объект spied (аннотированный с помощью @Spy) вместо макета (аннотированный с помощью @Mock):

  • when(...) thenReturn(...) делает реальный вызов метода перед возвратом указанного значения. Поэтому, если вызываемый метод выбрасывает исключение, вы должны иметь дело с ним/издеваться над ним и т.д. Конечно, вы все равно получите свой результат (что вы определяете в thenReturn(...))

  • doReturn(...) when(...) не вызывает метод вообще.

Пример:

public class MyClass {
     protected String methodToBeTested() {
           return anotherMethodInClass();
     }

     protected String anotherMethodInClass() {
          throw new NullPointerException();
     }
}

Тест:

@Spy
private MyClass myClass;

// ...

// would work fine
doReturn("test").when(myClass).anotherMethodInClass();

// would throw a NullPointerException
when(myClass.anotherMethodInClass()).thenReturn("test");

Ответ 4

Продолжаем этот ответ. Есть еще одно отличие: если вы хотите, чтобы ваш метод возвращал разные значения, например, когда он впервые был вызван, второй раз вызывал и т.д., тогда вы может передавать значения, например,...

PowerMockito.doReturn(false, false, true).when(SomeClass.class, "SomeMethod", Matchers.any(SomeClass.class));

Таким образом, он вернет false, когда метод вызывается в одном тестовом примере, а затем он вернет false снова и, наконец, true.

Ответ 5

Mockito javadoc, похоже, говорит, зачем использовать doReturn() вместо when() Используйте doReturn() в тех редких случаях, когда вы не можете использовать Mockito.when(Object).

Остерегайтесь, что Mockito.when(Object) всегда рекомендуется для обрезки потому что это аргумент типа безопасный и более читаемый (особенно когда последовательные вызовы).

Вот те редкие случаи, когда doReturn() подходит:

1. При шпионаже реальных объектов и вызова реальных методов на шпионах эффекты

List list = new LinkedList(); List spy = spy(list);

//Невозможно: реальный метод называется так spy.get(0) throws IndexOutOfBoundsException (список еще не заполнен)

when(spy.get(0)).thenReturn("foo");

//Вы должны использовать doReturn() для stubbing: doReturn("foo").when(spy).get(0);

2. Переопределение предыдущего исключения:

when(mock.foo()).thenThrow(new RuntimeException());

//Невозможно: метод foo(), исключенный для исключения, называется так Исключение RuntimeException. when(mock.foo()).thenReturn("bar");

//Вы должны использовать doReturn() для stubbing:

doReturn("bar").when(mock).foo(); В приведенных выше сценариях показан компромисс элегантного синтаксиса Mockito. Обратите внимание, что сценарии очень редки, хоть. Шпионаж должен быть спорадическим, а исключающее исключение - очень редкий. Не говоря уже о том, что в целом переустановка потенциальный запах кода, который указывает на слишком много стуков.

Ответ 6

"mock" может имитировать объект вместо его создания, "шпион" может создать фактический объект с фактическими параметрами. Когда мы делаем unit test, мы часто используем их. Но 'когда (xxx).thenReturn(xxx)' используется для mock и 'doReturn (xxx).when(xxx)', используемый для шпиона.