130 votes

Comparaison entre Mockito et JMockit - pourquoi Mockito est-il mieux voté que JMockit ?

Je cherche à savoir quel framework de mocking utiliser pour mon projet et je me suis arrêté sur les suivants JMockit y Mockito .

Je remarque que Mockito a été voté " le meilleur cadre de simulation pour Java " sur Stackoverflow.
En comparant les caractéristiques sur JMockit 's " Matrice de comparaison des outils de moquerie "il apparaît que JMockit a de multiples caractéristiques différentes.

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

143voto

Hendy Irawan Points 4635

Mise à jour en septembre 2019 : Le seul framework de mocking supporté (par défaut) par Spring Boot es Mockito . Si vous utilisez Spring, la réponse est assez évidente.


Je dirais que la compétition est entre JMockit y PowerMock entonces Mockito .

Je laisserais jMock et EasyMock "simples" car ils n'utilisent que le proxy et CGLIB et n'utilisent pas l'instrumentation Java 5 comme les frameworks plus récents.

jMock n'a pas non plus eu de version stable pendant plus de 4 ans. jMock 2.6.0 a mis 2 ans à passer de RC1 à RC2, puis encore 2 ans avant d'être effectivement publié.

En ce qui concerne le Proxy et CGLIB par rapport à l'instrumentation :

(EasyMock et jMock) sont basés sur java.lang.reflect.Proxy, qui nécessite l'implémentation d'une interface être implémentée. De plus, ils supportent la création d'objets fantaisie pour les classes par la génération de sous-classes de CGLIB. De ce fait, lesdites classes ne peuvent pas être finales et seules les méthodes d'instance surchargées peuvent être faire l'objet d'une moquerie. Mais le plus important, lorsqu'on utilise ces outils, les dépendances du code testé (c'est-à-dire les c'est-à-dire les objets d'autres classes sur lesquels dont une classe testée donnée dépend) doivent être contrôlées par l'outil tests, afin que des instances fantaisie puissent être passées aux clients de ces dépendances. Par conséquent, les dépendances ne peuvent pas être simplement instanciées avec l'opérateur new operator dans une classe cliente pour pour laquelle nous voulons écrire des tests unitaires.

En définitive, les limitations techniques des outils d'imitation conventionnels imposent les restrictions de conception suivantes sur code de production :

  1. Chaque classe qui peut avoir besoin d'être simulée dans un test doit soit implémenter une interface séparée ou ne pas être finale.
  2. Les dépendances de chaque classe à tester doivent être soit obtenues par des méthodes de création d'instance configurables configurables (fabriques ou Service Locator), soit être exposées à l'injection de dépendances. l'injection de dépendances. Sinon, les tests unitaires ne pourront pas ne pourront pas passer des implémentations fantaisie des dépendances à l'unité testée. testée.
  3. Étant donné que seules les méthodes d'instance peuvent être simulées, les classes devant faire l'objet d'un test unitaire sont les suivantes ne peuvent pas appeler de méthodes statiques sur leurs dépendances, ni les instancier ni les instancier en utilisant l'un de leurs constructeurs.

Ce qui précède est copié de http://jmockit.org/about.html . En outre, il compare lui-même (JMockit), PowerMock et Mockito de plusieurs façons :

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

JMockit vs PowerMock

  • Tout d'abord, PowerMock ne fournit pas une API complète pour le mocking, mais fonctionne plutôt comme une extension à un autre outil, qui actuellement peut être EasyMock ou Mockito. Ceci est évidemment un avantage pour les utilisateurs existants de ces outils.
  • JMockit, quant à lui, fournit des API entièrement nouvelles, bien que bien que son API principale (Expectations) soit similaire à la fois à EasyMock et à jMock. Bien que cela crée une courbe d'apprentissage plus longue, cela permet également à JMockit de fournir une plus simple, plus cohérente, et plus facile 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 à faire appel à des des appels d'API spécifiques pour traiter divers types de constructions linguistiques qui peuvent être présents dans le code de production : méthodes statiques (mockStatic(ClassA.class)), constructeurs (supprimer(constructeur(ClassXyz.class)), invocations de constructeurs (expectNew(AClass.class)), des mocks partiels (createPartialMock). mocks (createPartialMock(ClassX.class, "methodToMock")), etc.
  • Avec JMockit Expectations, toutes sortes de méthodes et de constructeurs sont simulés de manière purement déclarative, avec des simulations partielles spécifiées par expressions régulières dans l'annotation @Mocked ou simplement par "un-mocking". les membres sans attentes enregistrées. attentes enregistrées, c'est-à-dire que le développeur déclare simplement des "champs partagés pour la classe de test, ou des ou des "champs fantaisie locaux" et/ou des "paramètres paramètres" pour les méthodes de test individuelles (et dans ce dernier cas, l'objet l'annotation @Mocked ne sera souvent pas nécessaire).
  • Certaines capacités disponibles dans JMockit, telles que la prise en charge de l'asservissement (mocking), sont disponibles. equals et hashCode, les méthodes overridden et d'autres, ne sont pas actuellement supportées par PowerMock. De plus, il n'y a pas d'équivalent à la capacité de JMockit de capturer des instances et de simuler des implémentations de base spécifiées spécifiés pendant l'exécution du test, sans le code de test lui-même n'a aucune connaissance de l'implémentation réelle des classes.
  • 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 à conflits avec des bibliothèques tierces, d'où la nécessité d'utiliser parfois l'option @PowerMockIgnore("package.to.be.ignored") sur les classes de test.
  • Le mécanisme utilisé par JMockit (instrumentation au moment de l'exécution par le biais d'un fichier "agent Java") est plus simple et plus sûr, bien qu'il nécessite de passer un paramètre paramètre "-javaagent" à la JVM lors du le développement sur JDK 1.5 ; sur JDK 1.6+ (qui peut toujours être utilisé pour le développement d'une application). (qui peut toujours être utilisé pour le développement, même si le déploiement se fait sur une ancienne version), il n'y a pas de telle exigence, puisque JMockit peut charger de manière transparente l'agent Java à la demande en utilisant l'API Attach.

Un autre outil d'imitation récent est Mockito. Bien qu'il ne cherche pas à de surmonter les limites des outils plus anciens (jMock, EasyMock), il introduit un nouveau introduit un nouveau style de test de comportement de test de comportement avec les mocks. JMockit supporte également supporte également ce style alternatif, à travers l'API de vérification.

JMockit vs Mockito

  • Mockito s'appuie sur des appels explicites à son API afin de séparer le code entre les phases d'enregistrement (when(...)) et de vérifier (verify(...)). Ceci Cela signifie que toute invocation à un objet mock dans le code de test nécessitera également un appel à l'API de mocking. De plus, cela conduira souvent à répétitifs when(...) et verify(mock)... appels répétitifs.
  • Avec JMockit, aucun appel similaire n'existe. Bien sûr, nous avons les nouvelles fonctions NonStrictExpectations() et le nouvel appel de constructeur vérifications(), mais ils ne se produisent qu'une fois par test (typiquement), et sont complètement complètement séparés des invocations aux méthodes et constructeurs simulés.
  • L'API Mockito contient plusieurs incohérences dans la syntaxe utilisée pour les éléments suivants les invocations aux méthodes simulées. Dans la phase phase d'enregistrement, nous avons des appels comme when(mock.mockedMethod(args))... while dans la phase de vérification, ce même appel sera écrit comme verify(mock).mockedMethod(args). Notez que dans le premier cas, l'invocation de l'invocation de mockedMethod est effectuée directement sur l'objet fantaisie, alors que dans deuxième cas, elle est faite sur l'objet retourné par verify(mock).
  • JMockit n'a pas de telles incohérences car les invocations à méthodes moquées sont toujours faites directement sur les instances simulées elles-mêmes. (Avec une seule exception : pour faire correspondre des invocations sur la même instance simulée, un appel onInstance(mock) est utilisé, ce qui donne un code comme onInstance(mock).mockedMethod(args) ; la plupart des tests n'auront pas besoin d'utiliser cela, cependant).
  • Tout comme d'autres outils de simulation qui reposent sur des méthodes méthodes, Mockito se heurte aussi à une syntaxe syntaxe incohérente lorsque l'on stubbe 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 une méthode void. Avec JMockit, c'est toujours la même syntaxe : mockedList.clear() ; result = new RuntimeException() ;.
  • Une autre incohérence se produit dans l'utilisation des espions Mockito : les "mocks" qui permettent aux méthodes réelles d'être d'être exécutées sur l'instance espionnée. Pour Par exemple, si spy fait référence à une vide, au lieu d'écrire when(spy.get(0)).thenReturn("foo") vous devrez devrez écrire doReturn("foo").when(spy).get(0)). Avec JMockit, la fonctionnalité de mocking dynamique fournit une fonctionnalité similaire à celle des espions, mais sans ce problème puisque les méthodes réelles ne sont exécutées que pendant la phase de relecture.
  • Dans EasyMock et jMock, les premières API de mocking pour Java, l'accent était entièrement mis sur entièrement sur l'enregistrement des invocations invocations attendues des méthodes moquées, pour les objets fantaisie qui (par défaut) ne permettent pas permettent pas d'invocations inattendues. Ces APIs fournissent également l'enregistrement des invocations autorisées pour les objets fantaisie qui permettent des invocations inattendues, mais cela a été traité comme une fonctionnalité de seconde classe. De plus, avec ces outils, il n'y a aucun moyen de vérifier explicitement vérifier explicitement les invocations de mocks après que le code testé est exercé. Toutes ces vérifications sont effectuées implicitement et automatiquement.
  • Dans Mockito (et aussi dans Unitils Mock), le point de vue opposé est adopté. Toutes les invocations aux objets fantaisie 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 l'exercice du code testé est exercé, jamais automatiquement.
  • Les deux approches sont trop extrêmes, et par conséquent moins qu'optimales. Attentes et vérifications de JMockit est la seule API qui permet à l développeur de choisir de manière transparente la meilleure combinaison d'attentes strictes (attendues par défaut) et non strictes (autorisées par par défaut) d'invocations d'objets fantaisie pour chaque test.
  • Pour être plus clair, l'API Mockito présente le défaut suivant. Si vous devez vérifier qu'une invocation à une méthode fantaisie non-vide s'est produite pendant le test, mais que le test nécessite une valeur de retour de cette méthode qui est différente de la valeur par défaut pour le type de retour type de retour, alors le test Mockito aura du code en double : un when(mock.someMethod()).thenReturn(xyz) dans la phase d'enregistrement, et un appel verify(mock).someMethod() dans la phase de phase de vérification. Avec JMockit, une attente stricte attente peut toujours être enregistrée, qui n'aura pas besoin d'être explicitement vérifiée. Alternativement, une invocation d'invocations (times = 1) peut être spécifiée pour toute attente non stricte enregistrée enregistrée (avec Mockito, de telles contraintes peuvent seulement être spécifiées dans un appel verify(mock, contrainte)).
  • Mockito a une mauvaise syntaxe pour les vérifications dans l'ordre, et pour les vérifications complètes. vérifications (c'est-à-dire, vérifier que toutes les invocations aux objets fantaisie sont explicitement vérifiées). Dans le premier cas cas, un objet supplémentaire doit être créé, et des appels à la vérification doivent être faits sur sur lui : InOrder inOrder = inOrder(mock1, mock2, ...). Dans le second cas, les appels comme verifyNoMoreInteractions(mock) ou verifyZeroInteractions(mock1, mock2) doivent être effectués.
  • Avec JMockit, il suffit d'écrire new VerificationsInOrder() ou new FullVerifications() au lieu de new Verifications() (ou new FullVerificationsInOrder() pour combiner les les deux exigences). Il n'est pas nécessaire de préciser quels objets fantaisie sont concernés. Non d'appels supplémentaires à l'API de mocking. Et comme un bonus, en appelant unverifiedInvocations() dans un processus de bloc de vérification de commande, vous pouvez effectuer des vérifications liées à l'ordre qui sont tout simplement impossibles dans Mockito.

Enfin, la boîte à outils de test JMockit dispose d'une champ plus large y plus ambitieux objectifs que d'autres boîtes à outils d'asservissement, en afin de fournir une solution complète et complète et sophistiquée pour les développeurs des développeurs. Une bonne API pour le mocking, même sans limitations artificielles, ne suffit pas suffisante pour la création productive de tests. Un IDE-agnostique, 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 des outils de test pour les développeurs qui deviendra plus utile à mesure que la suite de tests augmente en taille la possibilité de réexécuter les tests de manière incrémentielle après une modification localisée du code de production Cette fonction est également incluse dans l'outil outil de couverture.

(il est vrai que la source peut être biaisée, mais bon...)

Je dirais que c'est JMockit . C'est le plus facile à utiliser, flexible, et il fonctionne dans presque 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.

24voto

Tumer Points 110

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

  • Mockito :

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

    • moquerie explicite
    • vérification implicite
  • JMockit :

    • supporte à la fois
  • En outre, d'autres avantages de JMockit :

    • si vous vous moquez des méthodes/constructeurs statiques, etc. (comme l'extension d'une très ancienne base de code 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 est, à mon avis, plus riche en fonctionnalités et plus flexible, mais qui nécessite une courbe d'apprentissage un peu plus raide. Il y a généralement plusieurs façons d'obtenir le même effet de simulation, ce qui nécessite plus de soin lors de la conception des simulations.

15voto

Joseph Erickson Points 1476

J'utilise jMockit uniquement à cause de ses bibliothèques de réflexion dans Deencapsultation.class. En fait, j'aime le style de Mockito, mais je refuse de modifier mon code et d'embrouiller mon API juste pour qu'un cadre de test limité puisse y accéder. Et je suis un fan du test de tout mon code, donc un framework qui ne peut pas facilement tester les 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 mocks.

10voto

Rogério Points 5460

Moi aussi, j'attends toujours une bonne comparaison technique entre Mockito (ou tout autre outil de mocking) et JMockit. Franchement, je dois dire que les tentatives de comparaison existantes ont été décevantes.

Jusqu'à présent, dans mes propres tentatives de compréhension et d'évaluation d'autres outils, j'ai établi les comparaisons suivantes : le matrice de caractéristiques (comme cela a déjà été souligné par d'autres) ; une section plus qualitative en cette page ; et cet exemple de suite de tests JUnit avec des tests équivalents écrits avec chaque API de simulation.

Il y a un nouveau série d'articles actuellement en cours d'écriture par quelqu'un d'autre qui compare EasyMock, JMockit, Mockito, etc. A article récent par le développeur d'EasyMock est également très intéressante.

4voto

Jeff Olson Points 2118

JMockit s'est avéré inestimable pour faciliter les tests de notre ancien code (avec de nombreux appels de méthodes statiques, etc.). [Shameless plug for an article sur mon blog]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X