Порівняння між Mockito і JMockit - чому Mockito проголосував краще за JMockit? [зачинено]


124

Я досліджую, який глузливий фреймворк використовувати для мого проекту, і звузив його до JMockit та Mockito .

Я зауважую, що Mockito був визнаний " найкращим фреймворком для Java " на Stackoverflow.
Якщо порівнювати функції на " Матриці порівняння інструментів для глузування " від JMockit, видно, що JMockit має кілька різних функцій.

Хтось має якусь конкретну інформацію (не думки) щодо того, що Mockito може зробити, чого неможливо досягти з JMockit і навпаки?


2
можливо краща зручність використання макіто, до речі, я не думаю, що JMockit зріліший за Mockito ...
Alois Cochard

42
Судячи з кількості голосів, ОБОВ'ЯЗКОВО відповіді на це питання громада дуже шукає. Що означає, що ортогоналізаційна стратегія цього сайту, яка спричинила закриття цього питання, потребує серйозного переосмислення - оскільки цей сайт часто наступає на ноги, щоб дати можливість відповісти, потрапляючи на його нерівну ортогональність. Не розуміючи, що в графічному аналізі дерева існує стільки способів переглянути ортогональність дерева, скільки є вузлів. Можливо, ортогональність цього сайту, а не питання, не узгоджена.
Блаженний Гек

9
+1 для не закриття. Ці відповіді мають величину цінності. Вибрати технологію непросто, і ці питання можуть заощадити багато часу. Дійсно, відповідь може не бути, але StackOverflow повинен відповідати на запитання без відповіді.
mhstnsc

6
Я додам свою підтримку тим, хто заявив, що закривати це як "не конструктивне" є смішним. Надані тут відповіді були підкріплені "фактами, посиланнями та / або експертизами". Питання в царині технологій, яке не вимагає якихось "дебатів, опитувань чи розширених дискусій", як правило, ледве варто задавати. Далі, надання фактів та досвіду залежить від різного досвіду - і ці відмінності призведуть до дискусій та розширених дискусій.
Джефф Найман

@Alois - чи можете ви навести конкретні приклади, коли JMockit виглядає менш зрілим, ніж Mockito?
NitinS

Відповіді:


140

Оновлення вересня 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. Через це згадані класи не можуть бути остаточними, і з них можна знущатись лише з методів, що перезаписуються. Найголовніше, однак, при використанні цих інструментів залежність коду, що перевіряється (тобто об'єкти інших класів, від яких залежить даний клас, який перевіряється), повинні контролюватися тестами, щоб макетні екземпляри могли передаватися клієнтам цих залежностей. Отже, залежності не можна просто встановити з новим оператором у класі клієнта, для якого ми хочемо написати тести одиниць.

Зрештою, технічні обмеження звичайних знущальних інструментів накладають такі дизайнерські обмеження на виробничий код:

  1. Кожен клас, який, можливо, потребує знущання в тесті, повинен або реалізувати окремий інтерфейс, або не бути остаточним.
  2. Залежності кожного класу, що підлягає тестуванню, повинні бути або отримані за допомогою налаштованих методів створення екземплярів (фабрики або локатор обслуговування), або піддаватися впливу ін'єкцій залежностей. В іншому випадку одиничні тести не зможуть передати макетні реалізації залежностей тестовому блоку.
  3. Оскільки тільки з методів екземплярів можна знущатися, класи, які піддаються тестуванню, не можуть викликати статичні методи залежно від їх залежностей, а також інстанціювати їх за допомогою будь-якого конструктора.

Зазначене скопійовано з http://jmockit.org/about.html . Крім того, він порівнює між собою (JMockit), PowerMock та Mockito кількома способами:

Зараз для Java є інші інструменти знущань, які також долають обмеження звичайних, між ними PowerMock, jEasyTest та MockInject. Найближчий до набору функцій JMockit - це PowerMock, тому я коротко його оціню тут (до того ж, інші два є більш обмеженими і, здається, вже не активно розвиваються).

JMockit проти PowerMock

  • Перш за все, PowerMock не забезпечує повний API для глузування, але натомість працює як розширення до іншого інструменту, який на даний момент може бути EasyMock або Mockito. Це, очевидно, перевага для існуючих користувачів цих інструментів.
  • З іншого боку, JMockit пропонує абсолютно нові API, хоча його основний API (очікування) схожий як на EasyMock, так і на jMock. Хоча це створює більш довгу криву навчання, вона також дозволяє JMockit надати більш простий, більш послідовний та простий у використанні API.
  • Порівняно з API очікувань JMockit API PowerMock є більш "низьким рівнем", що змушує користувачів розібратися та вказати, які класи потрібно підготувати до тестування (з анотацією @PrepareForTest ({ClassA.class, ...}) ) і вимагає конкретних викликів API для роботи з різними типами мовних конструкцій, які можуть бути присутніми у виробничому коді: статичні методи (mockStatic (ClassA.class)), конструктори (suppress (конструктор (ClassXyz.class))),) виклики конструктора ( очікуємоNew (AClass.class)), часткові макети (createPartialMock (ClassX.class, "methodToMock")) тощо
  • З очікуваннями JMockit всі види методів та конструкторів висміюються чисто декларативно, з частковим глузуванням, визначеним регулярними виразами в анотації @Mocked, або просто "відмежуванням" членів без зафіксованих очікувань; тобто розробник просто оголошує деякі спільні "макетні поля" для тестового класу, або якісь "локальні макетні поля" та / або "параметри макету" для окремих методів тестування (і в цьому останньому випадку анотація @Mocked часто не буде потрібні).
  • Деякі можливості, доступні в JMockit, такі як підтримка макетування рівних та хеш-кодів, перекритих методів та інших, наразі не підтримуються в PowerMock. Крім того, немає еквіваленту здатності JMockit захоплювати екземпляри та знущатися над реалізацією вказаних базових типів під час виконання тесту, без того, щоб сам тестовий код не мав ніяких знань про фактичні класи реалізації.
  • PowerMock використовує завантажувачі спеціального класу (як правило, по одному на тестовий клас), щоб генерувати модифіковані версії макетних класів. Настільки велике використання навантажувачів спеціальних класів може призвести до конфліктів із сторонніми бібліотеками, отже, потреба іноді використовувати тест @PowerMockIgnore ("package.to.be.ignored") на тестових класах.
  • Механізм, який використовується JMockit (інструментарій виконання через «агент Java»), простіший і безпечніший, хоча для розробки на JDK 1.5 потрібен передача параметра «-javaagent» JVM; в JDK 1.6+ (який завжди можна використовувати для розробки, навіть якщо розгортання на більш старій версії) немає такої вимоги, оскільки JMockit може прозоро завантажувати Java-агент на вимогу за допомогою API Attach.

Ще один останній інструмент глузування - Mockito. Хоча він не намагається подолати обмеження старих інструментів (jMock, EasyMock), він вводить новий стиль тестування поведінки з макетами. JMockit також підтримує цей альтернативний стиль через API підтвердження.

JMockit проти Mockito

  • Mockito покладається на явні виклики до свого API, щоб розділити код між записами (коли (...)) та перевірити (перевірити (...)) фази. Це означає, що будь-яке виклик до макетного об’єкта в тестовому коді також вимагатиме виклику до глузливого API. Крім того, це часто призводить до повторних викликів під час (...) та перевірки (знущань) ... дзвінків.
  • З JMockit подібних дзвінків не існує. Звичайно, у нас є нові виклики конструктора NonStrictExpe очікувань () та нові верифікації (), але вони трапляються лише один раз за тест (як правило) і повністю відокремлюються від викликів до знущаються методів та конструкторів.
  • API Mockito містить декілька невідповідностей у синтаксисі, який використовується для викликів методів глузування. На фазі запису у нас є виклики, як коли (mock.mockedMethod (args)) ... в той час як на фазі верифікації цей же виклик буде записаний як verify (mock) .mockedMethod (args). Зауважте, що в першому випадку виклик mockedMethod робиться безпосередньо на макетному об'єкті, тоді як у другому випадку він робиться на об'єкті, поверненому верифікацією (макетом).
  • У JMockit немає таких невідповідностей, оскільки виклики до методів глузування завжди робляться безпосередньо на самих знущаються екземплярах. (За винятком лише одного вибору: для відповідності викликам у тому ж знуреному екземплярі використовується виклик onInstance (mock), що призводить до такого коду, як onInstance (mock) .mockedMethod (args); хоча більшість тестів не потрібно використовувати це. )
  • Як і інші глузуючі інструменти, які покладаються на прив'язування / обгортання методів, Mockito також стикається з непослідовним синтаксисом під час заглушення методів недійсності. Наприклад, ви пишете, коли (mockedList.get (1))., ПотімThrow (новий RuntimeException ()); для недійсного методу і doThrow (новий RuntimeException ())., коли (mockedList) .clear (); за нікчемну. З JMockit це завжди той самий синтаксис: mockedList.clear (); результат = новий RuntimeException () ;.
  • Ще одна невідповідність виникає у використанні шпигунів Mockito: "макети", які дозволяють виконувати реальні методи на шпигунському екземплярі. Наприклад, якщо шпигун посилається на порожній Список, то замість того, щоб писати коли (spy.get (0)). Тоді повернути ("foo"), вам потрібно буде написати doReturn ("foo"). 0). З JMockit функція динамічного глузування забезпечує аналогічні функції шпигунів, але без цього питання, оскільки реальні методи виконуються лише на етапі повторного відтворення.
  • У EasyMock та jMock, перших API для глузування для Java, увага зосереджувалася повністю на записі очікуваних викликів знущаються методів, для об'єктів знущань, які (за замовчуванням) не дозволяють несподіваних викликів. Ці API також забезпечують запис дозволених викликів для макетних об'єктів, які дозволяють несподівано викликати, але це трактується як особливість другого класу. Крім того, за допомогою цих інструментів немає можливості явно перевірити виклики для макетів після використання тестового коду. Всі такі перевірки проводяться неявно та автоматично.
  • У Mockito (а також в Unitils Mock) приймається протилежна точка зору. Усі виклики для знущань над об'єктами, які можуть статися під час тесту, записані чи ні, дозволені, ніколи не очікувані. Перевірка проводиться явно після виконання тестового коду, ніколи автоматично.
  • Обидва підходи є надто екстремальними, а отже, менш оптимальними. Очікування та перевірки JMockit - єдиний API, який дозволяє розробникові безперешкодно вибирати найкращу комбінацію строгих (очікуваних за замовчуванням) та нестрогих (дозволених за замовчуванням) макетів викликів для кожного тесту.
  • Щоб бути більш зрозумілим, API Mockito має такий недолік. Якщо вам потрібно переконатися, що виклик до недійсного методу знущань стався під час тесту, але для тесту потрібно повернути значення цього методу, яке відрізняється від типового для типу повернення, тоді тест Mockito матиме повторюваний код: a, коли (mock.someMethod ()). тоді повертається (xyz) у фазі запису, а у фазі перевірки - verif (макет) .someMethod (). З JMockit завжди можна записати суворе очікування, яке не доведеться чітко перевіряти. Альтернативно, обмеження кількості викликів (разів = 1) може бути визначене для будь-яких записаних не суворих очікувань (при Mockito такі обмеження можуть бути вказані лише у виклику підтвердження (макет, обмеження)).
  • У Mockito є поганий синтаксис як для перевірки в порядку, так і для повної перевірки (тобто перевірки, що всі виклики для макетування об'єктів явно перевірені). У першому випадку потрібно створити додатковий об’єкт і викликати перевірку зроблених на ньому: InOrder inOrder = inOrder (mock1, mock2, ...). У другому випадку потрібно робити дзвінки, такі як verifyNoMoreInteractions (макет) або verifyZeroInteractions (mock1, mock2).
  • За допомогою JMockit ви просто пишете нову VerificationInOrder () або нову FullVerifications () замість нових Verification () (або новий FullVerificationsInOrder (), щоб поєднати обидві вимоги). Не потрібно вказувати, які макетні об’єкти задіяні. Немає зайвих глузуючих дзвінків API. І як бонус, зателефонувавши unverifiedInvocations () всередині впорядкованого блоку підтвердження, ви можете виконати перевірки, пов’язані з замовленнями, які просто неможливі в Mockito.

Нарешті, інструментарій тестування інструментів JMockit має ширший обсяг та амбітніші цілі, ніж інші глузливі набори інструментів, щоб забезпечити повноцінне та складне рішення для тестування розробників. Хорошого API для глузування, навіть без штучних обмежень, недостатньо для продуктивного створення тестів. IDE-агностик, простий у використанні та добре інтегрований інструмент покриття коду також є важливим, і саме це має на меті запропонувати JMockit Coverage. Ще один фрагмент набору інструментів для тестування розробників, який стане більш корисним у міру збільшення розміру тестового набору - це можливість поступового повторного повторного тестування після локальної зміни виробничого коду; це також включено в інструмент Покриття.

(надано, джерело може бути упередженим, але добре ...)

Я б сказав, що йдіть з JMockit . Це найпростіший у використанні, гнучкий, і працює у майже всіх випадках, навіть у складних ситуаціях та сценаріях, коли ви не можете керувати тестуваним класом (або ви не можете його зламати через причини сумісності тощо).

Мій досвід роботи з JMockit був дуже позитивним.


1
Я ніколи не використовував jmockit, але хотів би додати ще один аргумент до дискусії: подивіться на порівняння тенденцій google усіх обговорених рамок. Станом на 06.06.2012, JMockit навіть не відображається на графіку тенденцій google у порівнянні з Mockito та EasyMock. А кількість користувачів також важлива при виборі рамки.
техніка

3
Це досить дивно. Mockito та JMockIt дають мені відповідно 409 'та 83' удари в Google. Безумовно, JMockIt повинен проявитися принаймні.
торедж

5
Ваша відповідь дуже корисна. Я планував просто використовувати Mockito, але зараз спочатку випробую JMockit. Добре звучить, щоб не спробувати. @machinery: Так, важливо подивитися на тенденції, але обрати його як головний критерій обмежуватиме вас основним потоком та захищати від інновацій.
Діамон

1
Я знаю, що це стара тема, але прочитавши цю рецензію, я подумав, що також спробую. Треба сказати, на перший погляд, JMockit дуже перспективний. Однак на сьогоднішній день я вважаю, що підтримки громади для цього дуже бракує. У мене виникають великі проблеми з розумінням API Mock, і після публікації моїх проблем я не отримав відповіді протягом двох днів.
Ерік Б.

1
Відповіді 8 років, тому багато речей у відповіді не є більш правильними. Один момент полягає в тому, що JMockit вимагає -javaagentпрапор з 1,42, тому що ви більше не можете самостійно приєднатись, оскільки Java 9 і знайти відповідні робочі місця, очевидно, не входили в сферу розробника. Ще один момент полягає в тому, що JMockit більше не дозволяє знущатися над приватними методами та конструкторами, тоді як PowerMock робить afaik.
Вампір

24

Я працював з Mockito та JMockit, і мій досвід роботи з ними такий:

  • Мокіто:

    • неявна глузування (-> краща зручність використання, але загрожує не виявленням заборонених викликів методу на макетах)
    • явна перевірка
  • EasyMock:

    • explict глузувати
    • неявна перевірка
  • JMockit:

    • підтримує обоє
  • Крім того, інші переваги JMockit:

    • якщо ви знущаєтесь зі статичних методів / конструкторів тощо (наприклад, розширення старої бази застарілого коду без UT), у вас буде два варіанти: 1) Mockito / EasyMock з розширенням Powermock або 2) Jmockit
    • вбудований звіт про покриття

Я особисто віддаю перевагу JMockit, який, на мою думку, є більш насиченим та гнучким, але вимагає трохи більш крутої кривої навчання. Зазвичай існує декілька способів досягти однакового глузуючого ефекту і вимагає більше обережності при розробці макетів.


є stackoverflow.com/questions/8003278 / ... «verifyNoMoreInteractions» Я вважаю , що якщо ви хочете псевдо явні глузування з Mockito
rogerdpack

15

Я використовую jMockit лише тому, що це бібліотеки відображення в Deencapsultation.class. Я насправді люблю стиль Mockito, але я відмовляюся змінювати свій код і замульчувати свій API лише для того, щоб обмежитися рамкою тестування. І я прихильник тестування всього свого коду, тому рамка, яка не може легко перевірити приватні методи, - це не те, що я хочу використовувати.

Мене коливала ця стаття

Після (правда, великої) кривої навчання, jMockit зараз є моїм основним блоком тестування для макетів.


7
Можливо, якщо вам здається, що вам потрібно перевірити приватні методи, ви занадто переймаєтесь тим, як працює ваш код, а не тим, що він робить (що є реальним моментом, і що можна визначити, використовуючи лише його публічні методи). Також мені було б цікаво прочитати цю статтю, але посилання порушено.
кодова коробка

Через 4 роки ви все ще використовуєте jMockit в якості основної системи тестування? Я пробую це вперше і стикаюся з декількома проблемами, але не знаю, чи я нерозумію, як працює jMockit, чи це функція, яка просто не існує.
Ерік Б.

jMockit більше не підтримує тестування приватних методів. Клас деенкапсуляції повільно знищувався, а потім повністю видалявся у версії 1.47. jmockit.github.io/changes.html
Pytry

4

Для легкого тестування нашої застарілої кодової бази (з великою кількістю статичних викликів методів тощо), JMockit був безцінним. [Безсоромний модуль для статті в моєму блозі]


0

Я особисто віддаю перевагу EasyMock .
Можливість перемикатися між приємними, нормальними та суворими керуючими елементами управління - одна з моїх улюблених особливостей.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.