Comparaison entre Mockito et JMockit - pourquoi Mockito a-t-il été mieux voté que JMockit? [fermé]

124

J'étudie quel framework moqueur utiliser pour mon projet et je l'ai réduit à JMockit et Mockito .

Je remarque que Mockito a été élu " meilleur framework fictif pour Java " sur Stackoverflow.
En comparant les caractéristiques sur JMockit « de Mocking outil Matrice Comparaison » il apparaît que JMockit a plusieurs caractéristiques différentes.

Quelqu'un a-t-il des informations spécifiques (pas des opinions) sur ce que Mockito peut faire qui ne peut pas être réalisé avec JMockit et vice versa?

Rogério
la source
2
peut-être une meilleure convivialité pour mockito, btw je ne pense pas que JMockit est plus mature que Mockito ...
Alois Cochard
42
A en juger par le nombre de votes, les réponses à cette question sont évidemment très recherchées par la communauté. Ce qui signifie que la stratégie d'orthogonalisation de ce site qui a fait clore cette question doit être sérieusement repensée - en ce que ce site s'est fréquemment mis sur pied pour pouvoir apporter les réponses nécessaires en tombant sur son orthogonalité désalignée. Sans se rendre compte que dans l'analyse graphique d'un arbre, il y a autant de façons de visualiser l'orthogonalité d'un arbre que de nœuds. Peut-être que l'orthogonalité de ce site, plutôt que celle de la question, est mal alignée.
Blessed Geek
9
+1 pour ne pas fermer. Ces réponses ont beaucoup de valeur. Choisir une technologie n'est pas facile et ces questions peuvent faire gagner beaucoup de temps. En effet, il se peut qu'il n'y ait pas de bonne réponse, mais StackOverflow devrait accepter les questions sans réponse.
mhstnsc
6
J'ajouterai mon soutien à ceux qui déclarent qu'il est ridicule de conclure cela comme "non constructif". Les réponses fournies ici étaient étayées par «des faits, des références et / ou une expertise». Une question dans le domaine de la technologie qui ne suscite pas de «débats, sondages ou discussions prolongées» vaut généralement à peine la peine d'être posée. De plus, fournir des faits et une expertise repose sur des expériences différentes - et ces différences mèneront à un débat et à une discussion approfondie.
Jeff Nyman
@Alois - pouvez-vous donner des exemples concrets où JMockit semble moins mature que Mockito?
NitinS du

Réponses:

140

Mise à jour de septembre 2019: le seul cadre de simulation pris en charge (par défaut) par Spring Boot est Mockito . Si vous utilisez Spring, la réponse est assez évidente.


Je dirais que la concurrence est entre JMockit et PowerMock , puis Mockito .

Je laisserais jMock et EasyMock "simples" car ils n'utilisent que proxy et CGLIB et n'utilisent pas d'instrumentation Java 5 comme les nouveaux frameworks.

jMock n'avait pas non plus de version stable depuis plus de 4 ans. jMock 2.6.0 a nécessité 2 ans pour passer de RC1 à RC2, puis encore 2 ans avant d'être publié.

Concernant Proxy & CGLIB vs instrumentation:

(EasyMock et jMock) sont basés sur java.lang.reflect.Proxy, qui nécessite la mise en œuvre d'une interface. En outre, ils prennent en charge la création d'objets fictifs pour les classes via la génération de sous-classes CGLIB. Pour cette raison, lesdites classes ne peuvent pas être finales et seules les méthodes d'instance remplaçables peuvent être simulées. Plus important encore, cependant, lors de l'utilisation de ces outils, les dépendances du code testé (c'est-à-dire les objets d'autres classes dont dépend une classe donnée testée) doivent être contrôlées par les tests, afin que les instances fictives puissent être transmises aux clients de ces dépendances. Par conséquent, les dépendances ne peuvent pas simplement être instanciées avec l'opérateur new dans une classe client pour laquelle nous voulons écrire des tests unitaires.

En fin de compte, les limites techniques des outils de simulation conventionnels imposent les restrictions de conception suivantes sur le code de production:

  1. Chaque classe qui peut avoir besoin d'être simulée dans un test doit soit implémenter une interface distincte, soit ne pas être définitive.
  2. Les dépendances de chaque classe à tester doivent être obtenues via des méthodes de création d'instances configurables (usines ou localisateur de service), ou être exposées pour l'injection de dépendances. Sinon, les tests unitaires ne pourront pas transmettre des implémentations simulées de dépendances à l'unité sous test.
  3. Puisque seules les méthodes d'instance peuvent être simulées, les classes à tester par unité ne peuvent pas appeler de méthodes statiques sur leurs dépendances, ni les instancier en utilisant l'un des constructeurs.

Ce qui précède est copié de http://jmockit.org/about.html . De plus, il se compare (JMockit), PowerMock et Mockito de plusieurs manières:

Il existe maintenant d'autres outils de simulation pour Java qui surmontent également les limitations des outils conventionnels, entre eux PowerMock, jEasyTest et MockInject. Celui qui se rapproche le plus de l'ensemble des fonctionnalités de JMockit est PowerMock, je vais donc l'évaluer brièvement ici (en outre, les deux autres sont plus limités et ne semblent plus être activement développés).

JMockit contre PowerMock

  • Tout d'abord, PowerMock ne fournit pas d'API complète pour se moquer, mais fonctionne plutôt comme une extension d'un autre outil, qui peut actuellement être EasyMock ou Mockito. C'est évidemment un avantage pour les utilisateurs existants de ces outils.
  • JMockit, d'autre part, fournit des API entièrement nouvelles, bien que son API principale (attentes) soit similaire à EasyMock et jMock. Bien que cela crée une courbe d'apprentissage plus longue, cela permet également à JMockit de fournir une API plus simple, plus cohérente et plus facile à utiliser.
  • Par rapport à l'API JMockit Expectations, l'API PowerMock est plus "bas niveau", obligeant les utilisateurs à déterminer et à spécifier quelles classes doivent être préparées pour les tests (avec l'annotation @PrepareForTest ({ClassA.class, ...}) ) et nécessitant des appels API spécifiques pour traiter différents types de constructions de langage qui peuvent être présentes dans le code de production: méthodes statiques (mockStatic (ClassA.class)), constructeurs (suppress (constructor (ClassXyz.class))), invocations de constructeurs ( expectNew (AClass.class)), des simulations partielles (createPartialMock (ClassX.class, "methodToMock")), etc.
  • Avec JMockit Expectations, toutes sortes de méthodes et de constructeurs sont moqués de manière purement déclarative, avec des moqueries partielles spécifiées par des expressions régulières dans l'annotation @Mocked ou simplement en "dé-moquant" les membres sans attentes enregistrées; c'est-à-dire que le développeur déclare simplement des "champs simulés" partagés pour la classe de test, ou des "champs simulés locaux" et / ou des "paramètres simulés" pour des méthodes de test individuelles (et dans ce dernier cas, l'annotation @Mocked ne le fera pas souvent être nécessaire).
  • Certaines fonctionnalités disponibles dans JMockit, telles que la prise en charge de la simulation d'égaux et de hashCode, les méthodes remplacées et d'autres, ne sont actuellement pas prises en charge dans PowerMock. De plus, il n'y a pas d'équivalent à la capacité de JMockit à capturer des instances et à simuler des implémentations de types de base spécifiés lors de l'exécution du test, sans que le code de test lui-même n'ait aucune connaissance des classes d'implémentation réelles.
  • PowerMock utilise des chargeurs de classe personnalisés (généralement un par classe de test) afin de générer des versions modifiées des classes simulées. Une telle utilisation intensive de chargeurs de classes personnalisés peut conduire à des conflits avec des bibliothèques tierces, d'où la nécessité d'utiliser parfois l'annotation @PowerMockIgnore ("package.to.be.ignored") sur les classes de test.
  • Le mécanisme utilisé par JMockit (instrumentation d'exécution via un "agent Java") est plus simple et plus sûr, bien qu'il nécessite de passer un paramètre "-javaagent" à la JVM lors du développement sur JDK 1.5; sur JDK 1.6+ (qui peut toujours être utilisé pour le développement, même s'il est déployé sur une version plus ancienne), il n'y a pas une telle exigence, car JMockit peut charger de manière transparente l'agent Java à la demande en utilisant l'API Attach.

Un autre outil moqueur récent est Mockito. Bien qu'il ne tente pas de surmonter les limitations des anciens outils (jMock, EasyMock), il introduit un nouveau style de test de comportement avec des simulations. JMockit prend également en charge ce style alternatif, via l'API Verifications.

JMockit contre Mockito

  • Mockito s'appuie sur des appels explicites à son API afin de séparer le code entre les phases d'enregistrement (quand (...)) et de vérification (vérifier (...)). Cela signifie que toute invocation à un objet fictif dans le code de test nécessitera également un appel à l'API de simulation. De plus, cela conduira souvent à des appels répétitifs lorsque (...) et vérifier (simuler) ... des appels.
  • Avec JMockit, aucun appel similaire n'existe. Bien sûr, nous avons les nouveaux appels de constructeur NonStrictExpectations () et Verifications (), mais ils ne se produisent qu'une seule fois par test (généralement) et sont complètement séparés des appels aux méthodes et aux constructeurs simulés.
  • L'API Mockito contient plusieurs incohérences dans la syntaxe utilisée pour les appels aux méthodes simulées. Dans la phase d'enregistrement, nous avons des appels comme when (mock.mockedMethod (args)) ... tandis que dans la phase de vérification, ce même appel sera écrit comme verify (mock) .mockedMethod (args). Notez que dans le premier cas, l'appel à mockedMethod est effectué directement sur l'objet fictif, tandis que dans le second cas, il est fait sur l'objet renvoyé par verify (mock).
  • JMockit n'a pas de telles incohérences car les appels aux méthodes simulées sont toujours effectués directement sur les instances simulées elles-mêmes. (À une seule exception près: pour faire correspondre les appels sur la même instance simulée, un appel onInstance (simulé) est utilisé, ce qui donne un code comme onInstance (mock) .mockedMethod (args); la plupart des tests n'auront pas besoin de l'utiliser, cependant. )
  • Tout comme d'autres outils de simulation qui reposent sur le chaînage / l'encapsulation de méthodes, Mockito se heurte également à une syntaxe incohérente lors du stubbing des méthodes void. Par exemple, vous écrivez when (mockedList.get (1)). ThenThrow (new RuntimeException ()); pour une méthode non void, et doThrow (new RuntimeException ()). when (mockedList) .clear (); pour un vide. Avec JMockit, c'est toujours la même syntaxe: mockedList.clear (); result = new RuntimeException () ;.
  • Encore une autre incohérence se produit dans l'utilisation des espions Mockito: des "mocks" qui permettent aux méthodes réelles d'être exécutées sur l'instance espionnée. Par exemple, si spy fait référence à une liste vide, alors au lieu d'écrire when (spy.get (0)). ThenReturn ("foo"), vous devrez écrire doReturn ("foo"). When (spy) .get ( 0). Avec JMockit, la fonction de simulation dynamique fournit des fonctionnalités similaires aux espions, mais sans ce problème, car les méthodes réelles ne sont exécutées que pendant la phase de relecture.
  • Dans EasyMock et jMock, les premières API moqueuses pour Java, l'accent était entièrement mis sur l'enregistrement des appels attendus des méthodes simulées, pour les objets simulés qui (par défaut) ne permettent pas les appels inattendus. Ces API fournissent également l'enregistrement des appels autorisés pour les objets fictifs qui autorisent des appels inattendus, mais cela a été traité comme une fonctionnalité de deuxième classe. De plus, avec ces outils, il n'y a aucun moyen de vérifier explicitement les appels à des simulacres après que le code testé a été exercé. Toutes ces vérifications sont effectuées implicitement et automatiquement.
  • Dans Mockito (et aussi dans Unitils Mock), le point de vue opposé est pris. Toutes les invocations pour simuler des objets qui peuvent se produire pendant le test, qu'elles soient enregistrées ou non, sont autorisées, jamais attendues. La vérification est effectuée explicitement après que le code testé est exercé, jamais automatiquement.
  • Les deux approches sont trop extrêmes et par conséquent moins qu'optimales. JMockit Expectations & Verifications est la seule API qui permet au développeur de choisir de manière transparente la meilleure combinaison d'invocations simulées strictes (attendues par défaut) et non strictes (autorisées par défaut) pour chaque test.
  • Pour être plus clair, l'API Mockito présente le défaut suivant. Si vous avez besoin de vérifier qu'une invocation à une méthode simulée non vide s'est produite pendant le test, mais que le test nécessite une valeur de retour de cette méthode différente de la valeur par défaut pour le type de retour, le test Mockito aura un code en double: un appel when (mock.someMethod ()). thenReturn (xyz) dans la phase d'enregistrement, et un verify (mock) .someMethod () dans la phase de vérification. Avec JMockit, une attente stricte peut toujours être enregistrée, qui n'aura pas à être explicitement vérifiée. Alternativement, une contrainte de nombre d'appels (fois = 1) peut être spécifiée pour toute attente non stricte enregistrée (avec Mockito, de telles contraintes ne peuvent être spécifiées que dans un appel de vérification (simulation, contrainte)).
  • Mockito a une mauvaise syntaxe pour les vérifications dans l'ordre et pour les vérifications complètes (c'est-à-dire, vérifier que toutes les invocations à des objets simulés sont explicitement vérifiées). Dans le premier cas, un objet supplémentaire doit être créé, et des appels de vérification effectués dessus: InOrder inOrder = inOrder (mock1, mock2, ...). Dans le second cas, des appels tels que verifyNoMoreInteractions (mock) ou verifyZeroInteractions (mock1, mock2) doivent être effectués.
  • Avec JMockit, vous écrivez simplement de nouvelles VerificationsInOrder () ou de nouvelles FullVerifications () au lieu de nouvelles Verifications () (ou de nouvelles FullVerificationsInOrder () pour combiner les deux exigences). Pas besoin de spécifier quels objets factices sont impliqués. Aucun appel API moqueur supplémentaire. Et en prime, en appelant unverifiedInvocations () dans un bloc de vérification ordonnée, vous pouvez effectuer des vérifications liées à la commande qui sont tout simplement impossibles dans Mockito.

Enfin, la boîte à outils de test JMockit a une portée plus large et des objectifs plus ambitieux que les autres boîtes à outils de simulation, afin de fournir une solution de test complète et sophistiquée pour les développeurs. Une bonne API pour se moquer, même sans limitations artificielles, ne suffit pas pour la création productive de tests. Un outil de couverture de code indépendant de l'IDE, facile à utiliser et bien intégré est également essentiel, et c'est ce que JMockit Coverage vise à fournir. Un autre élément de l'ensemble d'outils de test des développeurs qui deviendra plus utile à mesure que la suite de tests augmentera en taille est la possibilité de réexécuter de manière incrémentielle les tests après une modification localisée du code de production; ceci est également inclus dans l'outil de couverture.

(d'accord, la source peut être biaisée, mais bon ...)

Je dirais d'aller avec JMockit . C'est le plus simple à utiliser, le plus flexible et fonctionne pour à peu près tous les cas, même les plus difficiles et les scénarios où vous ne pouvez pas contrôler la classe à tester (ou vous ne pouvez pas la casser pour des raisons de compatibilité, etc.).

Mes expériences avec JMockit ont été très positives.

Hendy Irawan
la source
1
Je n'ai jamais utilisé jmockit, mais j'aimerais ajouter un autre argument à la discussion: jetez un œil à une comparaison des tendances Google de tous les frameworks discutés. Depuis le 06.06.2012, JMockit n'apparaît même pas sur le graphique des tendances de Google par rapport à Mockito et EasyMock. Et le nombre d'utilisateurs est également important lors du choix d'un framework.
machinerie
3
C'est assez étrange. Mockito et JMockIt me donnent respectivement 409 'et 83' hits sur google. JMockIt devrait sûrement apparaître au moins.
thoredge
5
Votre réponse est très utile. J'avais prévu d'utiliser simplement Mockito, mais maintenant je vais d'abord tester JMockit. Cela semble trop bon de ne pas l'essayer. @machinery: Oui, il est important de regarder les tendances, mais le choisir comme critère principal vous limitera au flux principal et vous protégera de l'innovation.
démon
1
Je sais que c'est un vieux fil de discussion, mais après avoir lu cette critique, j'ai pensé que j'essaierais aussi. Je dois dire qu'en surface, JMockit est très prometteur. Cependant, à ce jour, j'ai trouvé que le soutien de la communauté était très insuffisant. J'ai un gros problème avec ma compréhension de l'API Mock et après avoir publié mes problèmes, je n'ai eu aucune réponse dans les 2 jours.
Eric B.
1
La réponse est de 8 ans, tant de choses dans la réponse ne sont plus correctes. Un point est que JMockit nécessite un -javaagentindicateur depuis 1.42 parce que vous ne pouvez plus vous auto-attacher depuis Java 9 et trouver des solutions de contournement appropriées n'était évidemment pas du ressort du développeur. Un autre point est que JMockit ne permet plus de se moquer des méthodes et des constructeurs privés alors que PowerMock fait un afaik.
Vampire du
24

J'ai travaillé avec Mockito et JMockit, et mon expérience avec eux est:

  • Mockito:

    • moquerie implicite (-> meilleure utilisabilité, mais risque de ne pas détecter les appels de méthode non autorisés sur les simulacres)
    • vérification explicite
  • EasyMock:

    • expliquer les moqueries
    • vérification implicite
  • JMockit:

    • prend en charge les deux
  • En outre, d'autres avantages de JMockit:

    • si vous vous moquez de méthodes / constructeurs statiques, etc. (comme l'extension d'une très ancienne base de code héritée sans UT), vous aurez deux choix: 1) Mockito / EasyMock avec l'extension Powermock ou 2) Jmockit
    • rapport de couverture intégré

Personnellement, je préfère JMockit, qui, à mon avis, est plus riche en fonctionnalités et plus flexible, mais nécessite une courbe d'apprentissage un peu plus raide. Il existe généralement plusieurs façons d'obtenir le même effet moqueur et nécessite plus de soin lors de la conception des simulacres.

Tumer
la source
il y a stackoverflow.com/questions/8003278/… "verifyNoMoreInteractions" Je suppose que si vous voulez des moqueries pseudo explicites avec mockito
rogerdpack
15

J'utilise jMockit uniquement cause de ses bibliothèques de réflexion dans Deencapsultation.class. J'adore le style de Mockito, mais je refuse de changer mon code et de brouiller mon API juste pour qu'un cadre de test limité puisse y parvenir. Et je suis fan de tester tout mon code, donc un framework qui ne peut pas facilement tester des méthodes privées n'est pas ce que je veux utiliser.

J'ai été influencé par cet article

Après une courbe d'apprentissage (certes importante), jMockit est maintenant mon principal cadre de test unitaire pour les simulations.

Joseph Erickson
la source
7
Peut-être que si vous sentez que vous avez besoin de tester des méthodes privées, vous êtes trop préoccupé par la façon dont votre code fonctionne, plutôt que par ce qu'il fait (quel est le vrai point, et qui peut être déterminé en n'exerçant que ses méthodes publiques). Je serais également intéressé de lire cet article, mais le lien est rompu.
codebox
4 ans plus tard, utilisez-vous toujours jMockit comme principal framework de test? Je l'essaie pour la première fois et rencontre quelques problèmes avec lui, mais je ne sais pas si c'est moi qui comprends mal comment jMockit fonctionne, ou si c'est une fonctionnalité qui n'existe tout simplement pas.
Eric B.
jMockit ne prend plus en charge les tests de méthodes privées. La classe Deencapsulation a été lentement déconseillée puis entièrement supprimée dans la version 1.47. jmockit.github.io/changes.html
Pytry
4

Pour tester facilement notre ancienne base de code (avec de nombreux appels de méthodes statiques, etc.), JMockit a été inestimable. [Prise sans vergogne pour un article sur mon blog]

Jeff Olson
la source
0

Personnellement, je préfère EasyMock .
La possibilité de passer d'un contrôle moqueur agréable, normal et strict est l'une de mes fonctionnalités préférées.

Bivas
la source