В чем разница между шуткой и шпионажем при использовании Mockito?
137
Каков был бы случай использования шпиона Mockito?
Мне кажется, что каждый случай использования шпиона может быть обработан с помощью макета, используя callRealMethod.
Одно отличие, которое я вижу, состоит в том, что если вы хотите, чтобы большинство вызовов методов были реальными, это экономит некоторые строки кода для использования имитатора против шпиона. Это или я скучаю по большей картине?
Наконец, после многих внутренних дискуссий и обсуждений в списке рассылки, в Mockito была добавлена частичная поддержка. Ранее мы рассматривали частичные насмешки как запахи кода. Тем не менее, мы нашли законный вариант использования для частичной имитации.
До релиза 1.8 spy () не производил реальных частичных насмешек, и это приводило некоторых в замешательство. Узнайте больше о шпионаже: здесь или в javadoc для метода spy (Object).
callRealMethod()был введен после spy(), но spy () был оставлен там, конечно, для обеспечения обратной совместимости.
В противном случае, вы правы: все методы шпиона реальны, если не заглушки. Все методы макета заглушаются, если не callRealMethod()вызывается. В целом, я бы предпочел использовать callRealMethod(), потому что это не заставляет меня использовать doXxx().when()идиому вместо традиционногоwhen().thenXxx()
Проблема в том, что в этих случаях предпочтение mock-а не шпионское, заключается в том, что класс использует член, который не вводится в него (но локально инициализируется), а затем используется «реальным» методом; в макете член будет инициализирован к его значению Java по умолчанию, которое может вызвать неправильное поведение или даже исключение NullPointerException. Чтобы пройти это, нужно добавить метод init, а затем «действительно» вызвать его, но мне это кажется немного преувеличенным.
Эяль Рот
Из документа: «Шпионов следует использовать осторожно и время от времени, например, когда имеешь дело с устаревшим кодом». Пространство модульного тестирования страдает от слишком многих способов сделать то же самое.
gdbj
89
Разница между шпионом и насмешкой
Когда Mockito создает макет - он делает это из класса типа, а не из фактического экземпляра. Макет просто создает пустой экземпляр оболочки класса, полностью оснащенный для отслеживания взаимодействий с ним. С другой стороны, шпион обернет существующий экземпляр. Он будет по-прежнему вести себя так же, как и обычный экземпляр, с той лишь разницей, что он также будет оснащен инструментами для отслеживания всех взаимодействий с ним.
В следующем примере - мы создаем макет класса ArrayList:
Как вы можете видеть - добавление элемента в макетированный список на самом деле ничего не добавляет - он просто вызывает метод без других побочных эффектов. С другой стороны, шпион будет вести себя по-другому - он на самом деле вызовет реальную реализацию метода add и добавит элемент в базовый список:
Здесь мы можем с уверенностью сказать, что был вызван настоящий внутренний метод объекта, потому что когда вы вызываете метод size (), вы получаете размер как 1, но этот метод size () не подвергался насмешкам! Так откуда же взялся 1? Внутренний реальный метод size () вызывается как size (), но не является насмешливым (или заглушенным), и, следовательно, мы можем сказать, что запись была добавлена к реальному объекту.
В первом примере, почему mockedList.size()возвращается, 0если этот метод не был заглушен? Это просто значение по умолчанию, учитывая тип возвращаемого значения метода?
Майк
@mike: mockedList.size()возвращает intзначение по умолчанию int0 в Java. Если вы попытаетесь выполнить assertEquals(0, mockedList.size());после mockedList.clear();, результат останется прежним.
realPK
2
Этот ответ хорошо и просто написан и помог мне, наконец, понять разницу между шуткой и шуткой. Хороший.
PesaThe
38
Если есть объект с 8 методами, и у вас есть тест, в котором вы хотите вызвать 7 реальных методов и один метод заглушки, у вас есть два варианта:
Используя макет, вы должны настроить его, вызвав 7 callRealMethod и заглушив один метод.
Используя, spyвы должны настроить его, заглушив один метод
Официальная документация по doCallRealMethodрекомендует использовать шпион для частичнога издевается.
См. Также javadoc spy (Object), чтобы узнать больше о частичных имитациях. Mockito.spy () - рекомендуемый способ создания частичных имитаций. Причина в том, что это гарантирует, что реальные методы вызываются против правильно сконструированного объекта, потому что вы несете ответственность за создание объекта, переданного методу spy ().
Разница между шпионом и насмешкой
Когда Mockito создает макет - он делает это из класса типа, а не из фактического экземпляра. Макет просто создает пустой экземпляр оболочки класса, полностью оснащенный для отслеживания взаимодействий с ним. С другой стороны, шпион обернет существующий экземпляр. Он будет по-прежнему вести себя так же, как и обычный экземпляр, с той лишь разницей, что он также будет оснащен инструментами для отслеживания всех взаимодействий с ним.
В следующем примере - мы создаем макет класса ArrayList:
Как вы можете видеть - добавление элемента в макетированный список на самом деле ничего не добавляет - он просто вызывает метод без других побочных эффектов. С другой стороны, шпион будет вести себя по-другому - он на самом деле вызовет реальную реализацию метода add и добавит элемент в базовый список:
Здесь мы можем с уверенностью сказать, что был вызван настоящий внутренний метод объекта, потому что когда вы вызываете метод size (), вы получаете размер как 1, но этот метод size () не подвергался насмешкам! Так откуда же взялся 1? Внутренний реальный метод size () вызывается как size (), но не является насмешливым (или заглушенным), и, следовательно, мы можем сказать, что запись была добавлена к реальному объекту.
Источник: http://www.baeldung.com/mockito-spy + собственные заметки.
источник
mockedList.size()
возвращается,0
если этот метод не был заглушен? Это просто значение по умолчанию, учитывая тип возвращаемого значения метода?mockedList.size()
возвращаетint
значение по умолчаниюint
0 в Java. Если вы попытаетесь выполнитьassertEquals(0, mockedList.size());
послеmockedList.clear();
, результат останется прежним.Если есть объект с 8 методами, и у вас есть тест, в котором вы хотите вызвать 7 реальных методов и один метод заглушки, у вас есть два варианта:
spy
вы должны настроить его, заглушив один методОфициальная документация по
doCallRealMethod
рекомендует использовать шпион для частичнога издевается.источник
Шпион может быть полезен, когда вы хотите создать модульные тесты для унаследованного кода .
Я создал выполнимый пример здесь https://www.surasint.com/mockito-with-spy/ , я скопировал некоторые из них здесь.
Если у вас есть что-то вроде этого кода:
Вам может не понадобиться шпион, потому что вы можете просто издеваться над DepositMoneyService и WithdrawMoneyService.
Но с некоторым устаревшим кодом зависимость находится в коде так:
Да, вы можете перейти к первому коду, но затем API будет изменен. Если этот метод используется во многих местах, вы должны изменить их все.
Альтернативой является то, что вы можете извлечь зависимость следующим образом:
Затем вы можете использовать шпион для вставки зависимости следующим образом:
Более подробно в ссылке выше.
источник
Mock
это голый двойной объект. Этот объект имеет те же сигнатуры методов, но реализация пуста и возвращает значение по умолчанию - 0 и нольSpy
является клонированным двойным объектом. Новый объект клонируется на основе реального объекта, но у вас есть возможность его смоделировать[Тест двойных типов]
источник