Обновление, сентябрь 2019 г .: единственный фреймворк mocking, поддерживаемый (по умолчанию) Spring Boot, это Mockito < / сильный>. Если вы используете Spring, ответ очевиден.
Я бы сказал, что конкуренция идет между JMockit и PowerMock, затем Mockito.
Я бы оставил "простые" jMock и EasyMock, потому что они используют только прокси и CGLIB и не используют инструментарий Java 5, как более новые фреймворки.
У jMock также не было стабильной версии более 4 лет. jMock 2.6.0 потребовалось 2 года для перехода от RC1 к RC2, а затем еще 2 года, прежде чем он был выпущен.
Что касается прокси и CGLIB по сравнению с инструментарием:
(EasyMock и jMock) основаны на java.lang.reflect.Proxy, который требует реализации интерфейса. Кроме того, они поддерживают создание фиктивных объектов для классов посредством генерации подклассов CGLIB. Из-за этого указанные классы не могут быть окончательными, и можно смоделировать только переопределяемые методы экземпляра. Однако наиболее важно то, что при использовании этих инструментов зависимости тестируемого кода (то есть объекты других классов, от которых зависит данный тестируемый класс) должны контролироваться тестами, чтобы фиктивные экземпляры могли передаваться клиентам. этих зависимостей. Следовательно, зависимости не могут быть просто созданы с помощью нового оператора в клиентском классе, для которого мы хотим написать модульные тесты.
В конечном итоге технические ограничения обычных инструментов имитации накладывают следующие конструктивные ограничения на производственный код:
- Каждый класс, который может потребоваться имитировать в тесте, должен либо реализовывать отдельный интерфейс, либо не быть окончательным.
- Зависимости каждого тестируемого класса должны быть либо получены с помощью настраиваемых методов создания экземпляров (фабрики или указатель служб), либо быть предоставлены для внедрения зависимостей. В противном случае модульные тесты не смогут передавать имитационные реализации зависимостей в тестируемый модуль.
- Поскольку имитировать можно только методы экземпляра, классы, подлежащие модульному тестированию, не могут вызывать какие-либо статические методы для своих зависимостей или создавать их экземпляры с помощью каких-либо конструкторов.
Вышеупомянутое скопировано с http://jmockit.org/about.html. Кроме того, он сравнивает себя (JMockit), PowerMock и Mockito несколькими способами:
Теперь существуют другие инструменты для имитации Java, которые также преодолевают ограничения обычных инструментов, в том числе PowerMock, jEasyTest и MockInject. Наиболее близким к набору функций JMockit является PowerMock, поэтому я кратко оценим его здесь (кроме того, два других более ограничены и, похоже, больше не разрабатываются активно).
JMockit против PowerMock
- Прежде всего, PowerMock не предоставляет полный API для имитации, а вместо этого работает как расширение другого инструмента, которым в настоящее время может быть EasyMock или Mockito. Очевидно, что это преимущество для существующих пользователей этих инструментов.
- JMockit, с другой стороны, предоставляет совершенно новые API, хотя его основной API (Expectations) похож как на EasyMock, так и на jMock. Хотя это создает более длительную кривую обучения, это также позволяет JMockit предоставлять более простой, согласованный и легкий в использовании API.
- По сравнению с JMockit Expectations API, PowerMock API является более «низкоуровневым», заставляя пользователей выяснять и указывать, какие классы необходимо подготовить для тестирования (с аннотацией @PrepareForTest ({ClassA.class, ...}) ) и требуя определенных вызовов API для работы с различными типами языковых конструкций, которые могут присутствовать в производственном коде: статические методы (mockStatic (ClassA.class)), конструкторы (подавить (constructor (ClassXyz.class))), вызовы конструкторов ( expectNew (AClass.class)), частичные имитации (createPartialMock (ClassX.class, «methodToMock»)) и т. д.
- С JMockit Expectations все виды методов и конструкторов имитируются чисто декларативным способом, с частичным имитированием, указанным с помощью регулярных выражений в аннотации @Mocked, или просто «демокингом» членов без записанных ожиданий; то есть разработчик просто объявляет некоторые общие «фиктивные поля» для тестового класса или некоторые «локальные фиктивные поля» и / или «фиктивные параметры» для отдельных методов тестирования (и в этом последнем случае аннотация @Mocked часто не быть нужным).
- Некоторые возможности, доступные в JMockit, такие как поддержка имитации равенства и hashCode, переопределенных методов и другие, в настоящее время не поддерживаются в PowerMock. Кроме того, нет эквивалента способности JMockit захватывать экземпляры и имитировать реализации указанных базовых типов во время выполнения теста, если сам тестовый код не знает реальных классов реализации.
- PowerMock использует пользовательские загрузчики классов (обычно по одному на тестовый класс) для создания модифицированных версий имитируемых классов. Такое интенсивное использование пользовательских загрузчиков классов может привести к конфликтам со сторонними библиотеками, поэтому иногда возникает необходимость использовать аннотацию @PowerMockIgnore («package.to.be.ignored») в тестовых классах.
- Механизм, используемый JMockit (инструментарий времени выполнения с помощью «Java-агента»), проще и безопаснее, хотя он требует передачи параметра «-javaagent» в JVM при разработке на JDK 1.5; в JDK 1.6+ (который всегда можно использовать для разработки, даже если выполняется развертывание в более старой версии) такого требования нет, поскольку JMockit может прозрачно загружать агент Java по запросу с помощью Attach API.
Еще один недавний инструмент для насмешек - Mockito. Хотя он не пытается преодолеть ограничения старых инструментов (jMock, EasyMock), он вводит новый стиль тестирования поведения с помощью имитаций. JMockit также поддерживает этот альтернативный стиль через API проверки.
JMockit против Mockito
- Mockito полагается на явные вызовы своего API, чтобы разделить код между этапами записи (когда (...)) и проверки (проверка (...)). Это означает, что для любого вызова фиктивного объекта в тестовом коде также потребуется вызов фиктивного API. Кроме того, это часто приводит к повторяющимся вызовам when (...) и verify (mock) ....
- В JMockit подобных вызовов не существует. Конечно, у нас есть вызовы конструкторов new NonStrictExpectations () и new Verification (), но они происходят только один раз за тест (обычно) и полностью отделены от вызовов имитируемых методов и конструкторов.
- API Mockito содержит несколько несоответствий в синтаксисе, используемом для вызовов имитируемых методов. На этапе записи у нас есть такие вызовы, как when (mock.mockedMethod (args)) ... в то время как на этапе проверки этот же вызов будет записан как verify (mock) .mockedMethod (args). Обратите внимание, что в первом случае вызов mockedMethod выполняется непосредственно для фиктивного объекта, а во втором случае - для объекта, возвращаемого функцией verify (mock).
- JMockit не имеет таких несоответствий, потому что вызовы имитируемых методов всегда выполняются непосредственно на самих имитируемых экземплярах. (Только за одним исключением: для сопоставления вызовов одного и того же имитируемого экземпляра используется вызов onInstance (mock), в результате чего получается такой код, как onInstance (mock) .mockedMethod (args); однако в большинстве тестов это не требуется. )
- Как и другие насмешливые инструменты, которые полагаются на цепочку / упаковку методов, Mockito также сталкивается с несогласованным синтаксисом при замене методов void. Например, вы пишете when (mockedList.get (1)). ThenThrow (new RuntimeException ()); для непустого метода и doThrow (new RuntimeException ()). when (mockedList) .clear (); для недействительного. В JMockit всегда один и тот же синтаксис: mockedList.clear (); result = new RuntimeException () ;.
- Еще одна несогласованность возникает при использовании шпионов Mockito: «имитируют», которые позволяют выполнять реальные методы на шпионском экземпляре. Например, если шпион ссылается на пустой список, то вместо того, чтобы писать when (spy.get (0)). ThenReturn ("foo"), вам нужно будет написать doReturn ("foo"). When (spy) .get ( 0). В JMockit функция динамического имитации предоставляет возможности, аналогичные функциям шпионов, но без этой проблемы, поскольку настоящие методы выполняются только во время фазы воспроизведения.
- В EasyMock и jMock, первых имитирующих API для Java, основное внимание уделялось записи ожидаемых вызовов имитируемых методов для имитирующих объектов, которые (по умолчанию) не допускают неожиданных вызовов. Эти API-интерфейсы также обеспечивают запись разрешенных вызовов для фиктивных объектов, которые допускают неожиданные вызовы, но это рассматривалось как второстепенная функция. Кроме того, с помощью этих инструментов невозможно явно проверить вызовы имитаций после выполнения тестируемого кода. Все такие проверки выполняются неявно и автоматически.
- В Mockito (а также в Unitils Mock) используется противоположная точка зрения. Все вызовы имитационных объектов, которые могут произойти во время теста, независимо от того, записаны они или нет, разрешены и никогда не ожидаются. Проверка выполняется явно после выполнения тестируемого кода, а не автоматически.
- Оба подхода слишком экстремальны и, следовательно, менее чем оптимальны. JMockit Expectations & Verifications - единственный API, который позволяет разработчику легко выбирать лучшую комбинацию строгих (ожидаемых по умолчанию) и нестрогих (разрешенных по умолчанию) фиктивных вызовов для каждого теста.
- Чтобы быть более понятным, API Mockito имеет следующий недостаток. Если вам нужно убедиться, что во время теста произошел вызов непустого имитационного метода, но для теста требуется возвращаемое значение из этого метода, которое отличается от значения по умолчанию для возвращаемого типа, тогда тест Mockito будет иметь повторяющийся код: вызов when (mock.someMethod ()). thenReturn (xyz) на этапе записи и verify (mock) .someMethod () на этапе проверки. С JMockit всегда можно записать строгое ожидание, которое не нужно явно проверять. В качестве альтернативы, ограничение количества вызовов (раз = 1) может быть указано для любого записанного нестрогого ожидания (с Mockito такие ограничения могут быть указаны только в вызове verify (mock, constraint)).
- У Mockito плохой синтаксис для проверок по порядку и для полных проверок (то есть проверки того, что все вызовы имитирующих объектов явно проверены). В первом случае необходимо создать дополнительный объект и выполнить для него вызовы проверки: InOrder inOrder = inOrder (mock1, mock2, ...). Во втором случае необходимо выполнить такие вызовы, как verifyNoMoreInteractions (mock) или verifyZeroInteractions (mock1, mock2).
- Используя JMockit, вы просто пишете new VerificationsInOrder () или new FullVerifications () вместо new Verification () (или new FullVerificationsInOrder () для объединения обоих требований). Не нужно указывать, какие макеты задействованы. Никаких лишних имитирующих вызовов API. И в качестве бонуса, вызывая unverifiedInvocations () внутри упорядоченного блока проверки, вы можете выполнять проверки, связанные с заказом, что просто невозможно в Mockito.
Наконец, JMockit Testing Toolkit имеет более широкую область применения и более амбициозные цели, чем другие наборы инструментов для фиксации, чтобы предоставить полное и сложное решение для тестирования разработчиков. Хорошего API для mocking'а, даже без искусственных ограничений, недостаточно для продуктивного создания тестов. Независимый от IDE, простой в использовании и хорошо интегрированный инструмент Code Coverage также важен, и именно это JMockit Coverage стремится обеспечить. Еще одна часть набора инструментов для тестирования разработчика, которая станет более полезной по мере увеличения размера набора тестов, - это возможность постепенно повторно запускать тесты после локализованного изменения производственного кода; это также включено в инструмент покрытия.
(конечно, источник может быть предвзятым, но что ж ...)
Я бы посоветовал использовать JMockit. Это самый простой в использовании, гибкий и работает практически во всех случаях, даже в сложных и сценариях, когда вы не можете управлять тестируемым классом (или вы не можете его сломать из-за соображений совместимости и т. Д.).
Мой опыт работы с JMockit был очень положительным.
person
Hendy Irawan
schedule
22.06.2011