В настоящее время я использую 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");
Ответ 3
Последняя альтернатива используется для методов на mocks, которые возвращают void
.
Пожалуйста, посмотрите, например, здесь:
Как сделать mockito void методами с mockito
Ответ 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)', используемый для шпиона.