Comparación entre Mockito y JMockit: ¿por qué Mockito es votado mejor que JMockit? [cerrado]

124

Estoy investigando qué marco de simulación usar para mi proyecto y lo he reducido a JMockit y Mockito .

Noté que Mockito fue votado como " el mejor marco simulado para Java " en Stackoverflow.
En la comparación de características en JMockit 's ' que imita la herramienta de Comparación Matrix ' Parece que JMockit tiene varias características diferentes.

¿Alguien tiene alguna información específica (no opiniones) sobre lo que Mockito puede hacer que no se puede lograr con JMockit y viceversa?

Rogério
fuente
2
quizás mejor usabilidad para mockito, por cierto, no creo que JMockit sea más maduro que Mockito ...
Alois Cochard
42
A juzgar por el número de votos, OBVIAMENTE las respuestas a esta pregunta son muy buscadas por la comunidad. Lo que significa que la estrategia de ortogonalización de este sitio que hizo que esta pregunta se cerrara necesita un replanteamiento serio, ya que este sitio con frecuencia se ha puesto de pie para poder proporcionar las respuestas necesarias al caer en su ortogonalidad desalineada. Sin darse cuenta de que en el análisis gráfico de un árbol, hay tantas formas de ver la ortogonalidad de un árbol como nodos. Quizás la ortogonalidad de este sitio, en lugar de la pregunta, está desalineada.
Beato Geek
9
+1 por no cerrar. Estas respuestas tienen mucho valor. Elegir una tecnología no es fácil y estas preguntas pueden ahorrarle mucho tiempo. De hecho, puede que no haya una respuesta correcta, pero StackOverflow debería responder a las preguntas sin una respuesta.
mhstnsc
66
Agregaré mi apoyo a aquellos que afirman que cerrar esto como "no constructivo" es ridículo. Las respuestas proporcionadas aquí fueron respaldadas por "hechos, referencias y / o experiencia". Por lo general, apenas vale la pena hacer una pregunta en el ámbito de la tecnología que no solicite algunos "debates, encuestas o debates extensos". Además, proporcionar hechos y experiencia se basa en diferentes experiencias, y esas diferencias conducirán a un debate y una discusión extendida.
Jeff Nyman
@Alois: ¿puedes dar ejemplos concretos donde JMockit parezca menos maduro que Mockito?
Nitinas

Respuestas:

140

Actualización de septiembre de 2019: el único marco de simulación compatible (por defecto) con Spring Boot es Mockito . Si usa Spring, la respuesta es bastante obvia.


Yo diría que la competencia es entre JMockit y PowerMock , luego Mockito .

Dejaría jMock y EasyMock "simples" porque usan solo proxy y CGLIB y no usan instrumentación Java 5 como los marcos más nuevos.

jMock tampoco tuvo una versión estable durante más de 4 años. jMock 2.6.0 requirió 2 años para pasar de RC1 a RC2, y luego otros 2 años antes de que se lanzara.

Con respecto a Proxy y CGLIB vs instrumentación:

(EasyMock y jMock) se basan en java.lang.reflect.Proxy, que requiere una interfaz para implementarse. Además, admiten la creación de objetos simulados para clases a través de la generación de subclase CGLIB. Debido a eso, dichas clases no pueden ser finales y solo se pueden burlar los métodos de instancia reemplazables. Sin embargo, lo más importante es que cuando se utilizan estas herramientas, las dependencias del código bajo prueba (es decir, los objetos de otras clases de las que depende una clase determinada bajo prueba) deben ser controladas por las pruebas, de modo que se puedan pasar instancias simuladas a los clientes. de esas dependencias Por lo tanto, las dependencias no pueden simplemente instanciarse con el nuevo operador en una clase de cliente para la que queremos escribir pruebas unitarias.

En última instancia, las limitaciones técnicas de las herramientas de burla convencionales imponen las siguientes restricciones de diseño en el código de producción:

  1. Cada clase que deba ser burlada en una prueba debe implementar una interfaz separada o no ser final.
  2. Las dependencias de cada clase a probar deben obtenerse a través de métodos de creación de instancias configurables (fábricas o un Localizador de servicios), o exponerse para la inyección de dependencias. De lo contrario, las pruebas unitarias no podrán pasar implementaciones simuladas de dependencias a la unidad bajo prueba.
  3. Dado que solo se pueden burlar los métodos de instancia, las clases que se probarán en la unidad no pueden llamar a ningún método estático en sus dependencias, ni instanciarlos usando ninguno de los constructores.

Lo anterior se copia de http://jmockit.org/about.html . Además, se compara entre sí (JMockit), PowerMock y Mockito de varias maneras:

Ahora hay otras herramientas de simulación para Java que también superan las limitaciones de las convencionales, entre ellas PowerMock, jEasyTest y MockInject. El que se acerca más al conjunto de características de JMockit es PowerMock, por lo que lo evaluaré brevemente aquí (además, los otros dos son más limitados y ya no parecen estar desarrollados activamente).

JMockit vs PowerMock

  • En primer lugar, PowerMock no proporciona una API completa para burlarse, sino que funciona como una extensión a otra herramienta, que actualmente puede ser EasyMock o Mockito. Obviamente, esto es una ventaja para los usuarios existentes de esas herramientas.
  • JMockit, por otro lado, proporciona API completamente nuevas, aunque su API principal (Expectativas) es similar a EasyMock y jMock. Si bien esto crea una curva de aprendizaje más larga, también permite que JMockit proporcione una API más simple, más consistente y más fácil de usar.
  • En comparación con la API JMockit Expectations, la API PowerMock es más de "bajo nivel", lo que obliga a los usuarios a determinar y especificar qué clases deben prepararse para la prueba (con la anotación @PrepareForTest ({ClassA.class, ...}) ) y que requieren llamadas API específicas para tratar varios tipos de construcciones de lenguaje que pueden estar presentes en el código de producción: métodos estáticos (mockStatic (ClassA.class)), constructores (suprimir (constructor (ClassXyz.class))), invocaciones de constructores ( expectNew (AClass.class)), simulacros parciales (createPartialMock (ClassX.class, "methodToMock")), etc.
  • Con JMockit Expectations, todo tipo de métodos y constructores se burlan de una manera puramente declarativa, con burlas parciales especificadas a través de expresiones regulares en la anotación @Mocked o simplemente "desanimando" a los miembros sin expectativas registradas; es decir, el desarrollador simplemente declara algunos "campos simulados" compartidos para la clase de prueba, o algunos "campos simulados locales" y / o "parámetros simulados" para métodos de prueba individuales (y en este último caso la anotación @Mocked a menudo no lo hará) ser necesario).
  • Algunas capacidades disponibles en JMockit, como el soporte para burlarse de iguales y hashCode, métodos anulados y otros, actualmente no son compatibles con PowerMock. Además, no hay equivalente a la capacidad de JMockit para capturar instancias y simulaciones de implementaciones de tipos base específicos a medida que se ejecuta la prueba, sin que el código de la prueba tenga conocimiento de las clases de implementación reales.
  • PowerMock utiliza cargadores de clases personalizados (generalmente uno por clase de prueba) para generar versiones modificadas de las clases simuladas. Tal uso intensivo de cargadores de clases personalizados puede generar conflictos con bibliotecas de terceros, de ahí la necesidad de usar a veces la anotación @PowerMockIgnore ("package.to.be.ignored") en las clases de prueba.
  • El mecanismo utilizado por JMockit (instrumentación de tiempo de ejecución a través de un "agente Java") es más simple y seguro, aunque requiere pasar un parámetro "-javaagent" a la JVM cuando se desarrolla en JDK 1.5; en JDK 1.6+ (que siempre se puede usar para el desarrollo, incluso si se implementa en una versión anterior) no existe tal requisito, ya que JMockit puede cargar de forma transparente el agente Java a pedido mediante el uso de la API Attach.

Otra herramienta de burla reciente es Mockito. Aunque no intenta superar las limitaciones de las herramientas más antiguas (jMock, EasyMock), sí introduce un nuevo estilo de pruebas de comportamiento con simulacros. JMockit también admite este estilo alternativo, a través de la API de Verificaciones.

JMockit vs Mockito

  • Mockito se basa en llamadas explícitas a su API para separar el código entre el registro (cuando (...)) y las fases de verificación (verificación (...)). Esto significa que cualquier invocación a un objeto simulado en el código de prueba también requerirá una llamada a la API simulada. Además, esto a menudo dará lugar a repetitivas cuando (...) y verificar (simulacro) ... llamadas.
  • Con JMockit, no existen llamadas similares. Claro, tenemos las nuevas llamadas de constructor NonStrictExpectations () y las nuevas Verificaciones (), pero ocurren solo una vez por prueba (típicamente), y están completamente separadas de las invocaciones a métodos y constructores simulados.
  • La API de Mockito contiene varias inconsistencias en la sintaxis utilizada para las invocaciones a los métodos simulados. En la fase de registro, tenemos llamadas como when (mock.mockedMethod (args)) ... mientras que en la fase de verificación, esta misma llamada se escribirá como verificar (simulacro) .mockedMethod (args). Observe que en el primer caso la invocación a mockedMethod se realiza directamente en el objeto simulado, mientras que en el segundo caso se realiza en el objeto devuelto por verificar (simulacro).
  • JMockit no tiene tales inconsistencias porque las invocaciones a métodos simulados siempre se hacen directamente en las instancias simuladas. (Solo con una excepción: para hacer coincidir las invocaciones en la misma instancia simulada, se usa una llamada onInstance (simulacro), lo que da como resultado un código como onInstance (simulacro) .mockedMethod (args); sin embargo, la mayoría de las pruebas no necesitarán usar esto. )
  • Al igual que otras herramientas de burla que se basan en el encadenamiento / ajuste de métodos, Mockito también se encuentra con una sintaxis inconsistente al tropezar con métodos vacíos. Por ejemplo, escribe cuando (mockedList.get (1)). ThenThrow (new RuntimeException ()); para un método no nulo y doThrow (new RuntimeException ()). when (mockedList) .clear (); para un vacío Con JMockit, siempre es la misma sintaxis: mockedList.clear (); resultado = nueva RuntimeException () ;.
  • Otra inconsistencia ocurre en el uso de espías Mockito: "simulacros" que permiten que los métodos reales se ejecuten en la instancia espía. Por ejemplo, si el espía se refiere a una Lista vacía, en lugar de escribir cuándo (spy.get (0)). ThenReturn ("foo") deberá escribir doReturn ("foo"). When (spy) .get ( 0). Con JMockit, la función de burla dinámica proporciona una funcionalidad similar a la de los espías, pero sin este problema, ya que los métodos reales solo se ejecutan durante la fase de reproducción.
  • En EasyMock y jMock, las primeras API de simulación para Java, el enfoque se centraba completamente en la grabación de invocaciones esperadas de métodos simulados, para objetos simulados que (por defecto) no permiten invocaciones inesperadas. Esas API también proporcionan el registro de invocaciones permitidas para objetos simulados que permiten invocaciones inesperadas, pero esto se trató como una característica de segunda clase. Además, con estas herramientas no hay forma de verificar explícitamente las invocaciones a simulacros después de ejercer el código bajo prueba. Todas estas verificaciones se realizan implícita y automáticamente.
  • En Mockito (y también en Unitils Mock), se toma el punto de vista opuesto. Todas las invocaciones para burlarse de los objetos que pueden ocurrir durante la prueba, ya sean grabadas o no, están permitidas, nunca se esperan. La verificación se realiza explícitamente después de ejercer el código bajo prueba, nunca automáticamente.
  • Ambos enfoques son demasiado extremos y, en consecuencia, menos que óptimos. JMockit Expectations & Verifications es la única API que permite al desarrollador elegir sin problemas la mejor combinación de invocaciones simuladas estrictas (esperadas por defecto) y no estrictas (permitidas por defecto) para cada prueba.
  • Para ser más claro, la API de Mockito tiene la siguiente deficiencia. Si necesita verificar que una invocación a un método simulado no vacío ocurrió durante la prueba, pero la prueba requiere un valor de retorno de ese método que sea diferente del predeterminado para el tipo de retorno, entonces la prueba de Mockito tendrá un código duplicado: una llamada a (mock.someMethod ()). thenReturn (xyz) en la fase de registro, y una verificación (simulacro) .someMethod () en la fase de verificación. Con JMockit, siempre se puede registrar una expectativa estricta, que no tendrá que verificarse explícitamente. Alternativamente, se puede especificar una restricción de recuento de invocación (veces = 1) para cualquier expectativa no estricta registrada (con Mockito, tales restricciones solo se pueden especificar en una llamada de verificación (simulación, restricción).
  • Mockito tiene una sintaxis pobre para las verificaciones en orden y para verificaciones completas (es decir, verificar que todas las invocaciones para simular objetos se verifiquen explícitamente). En el primer caso, se debe crear un objeto adicional y se deben realizar llamadas para verificarlo: InOrder inOrder = inOrder (mock1, mock2, ...). En el segundo caso, se deben realizar llamadas como generate_MoreInteractions (simulacro) o VerifiedInterractions_Cero (simulacro1, simulacro2).
  • Con JMockit, simplemente escribe nuevas VerificationsInOrder () o nuevas FullVerifications () en lugar de nuevas Verifications () (o nuevas FullVerificationsInOrder () para combinar ambos requisitos). No es necesario especificar qué objetos simulados están involucrados. No hay llamadas API extra de burla. Y como beneficio adicional, al llamar a unverifiedInvocations () dentro de un bloque de verificación ordenado, puede realizar verificaciones relacionadas con el pedido que son simplemente imposibles en Mockito.

Finalmente, JMockit Testing Toolkit tiene un alcance más amplio y objetivos más ambiciosos que otros kits de herramientas de burla, con el fin de proporcionar una solución de prueba de desarrollador completa y sofisticada. Una buena API para burlarse, incluso sin limitaciones artificiales, no es suficiente para la creación productiva de pruebas. Una herramienta de Cobertura de Código bien integrada, fácil de usar y bien integrada por IDE también es esencial, y eso es lo que JMockit Coverage pretende proporcionar. Otra parte del conjunto de herramientas de prueba para desarrolladores que será más útil a medida que el conjunto de pruebas crezca en tamaño es la capacidad de volver a ejecutar las pruebas de forma incremental después de un cambio localizado en el código de producción; Esto también se incluye en la herramienta Cobertura.

(concedido, la fuente puede estar sesgada, pero bueno ...)

Yo diría que vayas con JMockit . Es el más fácil de usar, flexible y funciona para casi todos los casos, incluso los difíciles y los escenarios en los que no puede controlar la clase que se probará (o no puede romperla debido a razones de compatibilidad, etc.).

Mis experiencias con JMockit han sido muy positivas.

Hendy Irawan
fuente
1
Nunca he usado jmockit, pero me gustaría agregar otro argumento a la discusión: eche un vistazo a una comparación de tendencias de Google de todos los marcos discutidos. A partir del 06.06.2012, JMockit ni siquiera aparece en el gráfico de tendencias de Google en comparación con Mockito y EasyMock. Y el número de usuarios también es importante al elegir un marco.
maquinaria
3
Eso es bastante extraño. Mockito y JMock Me dieron respectivamente 409 'y 83' hits en google. Seguramente JMock debería aparecer al menos.
Thoredge
55
Tu respuesta es muy útil. Planeaba simplemente usar Mockito, pero ahora probaré JMockit primero. Suena bien no intentarlo. @machinery: Sí, es importante observar las tendencias, pero elegirlo como criterio principal lo restringirá a la corriente principal y lo protegerá de la innovación.
Deamon
1
Sé que este es un hilo viejo, pero después de leer esta crítica, pensé en probarlo también. Tengo que decir que, en la superficie, JMockit es muy prometedor. Sin embargo, hasta la fecha, he encontrado que el apoyo de la comunidad es muy deficiente. Tengo un gran problema con mi comprensión de la API simulada y después de publicar mis problemas, no he tenido respuesta en los 2 días.
Eric B.
1
La respuesta tiene 8 años, por lo que muchas cosas en la respuesta ya no son correctas. Un punto es que JMockit requiere un -javaagentindicador desde 1.42 porque ya no puede autoajustarse desde Java 9 y, obviamente, encontrar soluciones alternativas no estaba en el alcance del desarrollador. Otro punto es que JMockit ya no permite burlarse de métodos y constructores privados, mientras que PowerMock hace afaik.
Vampiro
24

Trabajé con Mockito y JMockit, y mi experiencia con ellos es:

  • Mockito

    • burla implícita (-> mejor usabilidad, pero tiene el peligro de no detectar llamadas a métodos no permitidos en simulacros)
    • verificación explícita
  • EasyMock:

    • burla explícita
    • verificación implícita
  • JMockit:

    • apoya a ambos
  • Además, otros beneficios de JMockit:

    • si se está burlando de métodos / constructores estáticos, etc. (como extender una base de código heredada muy antigua sin UT), tendrá dos opciones: 1) Mockito / EasyMock con extensión Powermock o 2) Jmockit
    • informe de cobertura incorporado

Personalmente, prefiero JMockit, que creo que es más rico en funciones y flexible, pero requiere una curva de aprendizaje un poco más pronunciada. Por lo general, hay varias formas de lograr el mismo efecto de burla y requiere más cuidado al diseñar las burlas.

Tumer
fuente
hay stackoverflow.com/questions/8003278/… "verificadoNoMoreInteractions" Supongo que si quieres una burla pseudo explícita con mockito
rogerdpack
15

Uso jMockit solo por sus bibliotecas de reflexión en Deencapsultation.class. De hecho, me encanta el estilo de Mockito, pero me niego a cambiar mi código y enturbiar mi API solo para que un marco de prueba limitado pueda obtenerlo. Y soy fanático de probar todo mi código, por lo que un marco que no puede probar fácilmente métodos privados no es lo que quiero usar.

Fui influenciado por este artículo

Después de una curva de aprendizaje (ciertamente grande), jMockit es ahora mi marco de prueba de unidad principal para simulacros.

Joseph Erickson
fuente
77
Quizás si siente que necesita probar métodos privados, le preocupa demasiado cómo funciona su código, en lugar de lo que hace (que es el punto real y que puede determinarse ejerciendo solo sus métodos públicos). Además, me interesaría leer ese artículo, pero el enlace está roto.
codebox
4 años después, ¿sigues usando jMockit como tu marco de prueba principal? Lo estoy probando por primera vez y me encuentro con algunos problemas, pero no sé si soy yo quien no entiende cómo funciona jMockit, o si es una característica que simplemente no existe.
Eric B.
jMockit ya no admite la prueba de métodos privados. La clase Deencapsulation fue obsoleta lentamente y luego eliminada por completo en la versión 1.47. jmockit.github.io/changes.html
Pytry
4

Para probar fácilmente nuestra base de código heredada (con muchas llamadas a métodos estáticos, etc.), JMockit ha sido invaluable. [Plug descarado para un artículo en mi blog]

Jeff Olson
fuente
0

Personalmente prefiero EasyMock .
La capacidad de desviar entre controles burlones agradables, normales y estrictos es una de mis características favoritas.

Bivas
fuente