Обновление, сентябрь 2019 г .: Единственный фреймворк для фиксации, поддерживаемый (по умолчанию) 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 Verifications (), но они происходят только один раз за тест (обычно) и полностью отделены от вызовов имитируемых методов и конструкторов.
- 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 для имитации, даже без искусственных ограничений, недостаточно для продуктивного создания тестов. Независимый от IDE, простой в использовании и хорошо интегрированный инструмент Code Coverage также важен, и это то, что JMockit Coverage стремится обеспечить. Еще одна часть набора инструментов для тестирования разработчика, которая станет более полезной по мере увеличения размера набора тестов, - это возможность постепенно повторно запускать тесты после локализованного изменения производственного кода; это также включено в инструмент покрытия.
(конечно, источник может быть предвзятым, но что ж ...)
Я бы посоветовал пойти с JMockit . Это самый простой в использовании, гибкий и работает практически во всех случаях, даже в сложных и сценариях, когда вы не можете контролировать тестируемый класс (или вы не можете его сломать из-за соображений совместимости и т. Д.).
Мой опыт работы с JMockit был очень положительным.