¿Cuál es el mejor marco para crear objetos simulados en Java? ¿Por qué? ¿Cuáles son los pros y los contras de cada marco?
¿Cuál es el mejor marco para crear objetos simulados en Java? ¿Por qué? ¿Cuáles son los pros y los contras de cada marco?
Respuestas:
He tenido buen éxito con Mockito .
Cuando intenté aprender sobre JMock y EasyMock, encontré que la curva de aprendizaje era un poco empinada (aunque tal vez solo soy yo).
Me gusta Mockito debido a su sintaxis simple y limpia que pude entender bastante rápido. La sintaxis mínima está diseñada para admitir muy bien los casos comunes, aunque las pocas veces que necesitaba hacer algo más complicado encontré que lo que quería era compatible y fácil de entender.
Aquí hay un ejemplo (abreviado) de la página de inicio de Mockito:
import static org.mockito.Mockito.*;
List mockedList = mock(List.class);
mockedList.clear();
verify(mockedList).clear();
No se vuelve mucho más simple que eso.
El único inconveniente importante que se me ocurre es que no se burlará de los métodos estáticos.
Soy el creador de PowerMock, así que obviamente debo recomendarlo. :-)
PowerMock extiende tanto EasyMock como Mockito con la capacidad de burlarse de métodos estáticos , métodos finales e incluso privados. El soporte de EasyMock está completo, pero el complemento Mockito necesita más trabajo. Estamos planeando agregar soporte para JMock también.
PowerMock no está destinado a reemplazar otros marcos, sino que se puede usar en situaciones difíciles cuando otros marcos no permiten la burla. PowerMock también contiene otras características útiles, como la supresión de inicializadores y constructores estáticos .
El sitio del proyecto JMockit contiene mucha información comparativa para los kits de herramientas de burla actuales.
En particular, consulte la matriz de comparación de características , que cubre EasyMock, jMock, Mockito, Unitils Mock, PowerMock y, por supuesto, JMockit. Intento mantenerlo lo más preciso y actualizado posible.
He tenido éxito con JMockit .
Es bastante nuevo, por lo que es un poco crudo y poco documentado. Utiliza ASM para redefinir dinámicamente el bytecode de la clase, por lo que puede simular todos los métodos, incluidos los estáticos, privados, constructores e inicializadores estáticos. Por ejemplo:
import mockit.Mockit;
...
Mockit.redefineMethods(MyClassWithStaticInit.class,
MyReplacementClass.class);
...
class MyReplacementClass {
public void $init() {...} // replace default constructor
public static void $clinit{...} // replace static initializer
public static void myStatic{...} // replace static method
// etc...
}
Tiene una interfaz Expectativas que también permite escenarios de grabación / reproducción:
import mockit.Expectations;
import org.testng.annotations.Test;
public class ExpecationsTest {
private MyClass obj;
@Test
public void testFoo() {
new Expectations(true) {
MyClass c;
{
obj = c;
invokeReturning(c.getFoo("foo", false), "bas");
}
};
assert "bas".equals(obj.getFoo("foo", false));
Expectations.assertSatisfied();
}
public static class MyClass {
public String getFoo(String str, boolean bool) {
if (bool) {
return "foo";
} else {
return "bar";
}
}
}
}
La desventaja es que requiere Java 5/6.
También puede echar un vistazo a las pruebas con Groovy. En Groovy, puede burlarse fácilmente de las interfaces de Java utilizando el operador 'as':
def request = [isUserInRole: { roleName -> roleName == "testRole"}] as HttpServletRequest
Además de esta funcionalidad básica, Groovy ofrece mucho más en el frente burlón, incluidos los poderosos MockFor
y las StubFor
clases.
Empecé a usar simulacros con EasyMock . Es bastante fácil de entender, pero el paso de repetición fue un poco molesto. Mockito elimina esto, también tiene una sintaxis más limpia, ya que parece que la legibilidad era uno de sus objetivos principales. No puedo enfatizar lo suficiente lo importante que es esto, ya que la mayoría de los desarrolladores pasarán su tiempo leyendo y manteniendo el código existente, sin crearlo.
Otra cosa buena es que las interfaces y las clases de implementación se manejan de la misma manera, a diferencia de EasyMock, donde aún debe recordar (y verificar) para usar una extensión de clase EasyMock.
He echado un vistazo rápido a JMockit recientemente, y aunque la lista de características es bastante completa, creo que el precio de esto es la legibilidad del código resultante y tener que escribir más.
Para mí, Mockito da en el blanco, siendo fácil de escribir y leer, y lidiando con la mayoría de las situaciones que requerirá la mayoría del código. Usar Mockito con PowerMock sería mi elección.
Una cosa a tener en cuenta es que la herramienta que elegirías si estuvieras desarrollando solo, o en un pequeño equipo muy unido, podría no ser la mejor opción para una gran empresa con desarrolladores de diferentes niveles de habilidad. La legibilidad, la facilidad de uso y la simplicidad necesitarían más consideración en este último caso. No tiene sentido obtener el marco de burla definitivo si muchas personas terminan sin usarlo o no mantienen las pruebas.
Estamos usando EasyMock y EasyMock Class Extension en el trabajo y estamos muy contentos con eso. Básicamente te da todo lo que necesitas. Eche un vistazo a la documentación, hay un buen ejemplo que le muestra todas las características de EasyMock.
Usé JMock temprano. Probé Mockito en mi último proyecto y me gustó. Más conciso, más limpio. PowerMock cubre todas las necesidades que están ausentes en Mockito, como burlarse de un código estático, burlarse de la creación de una instancia, burlarse de las clases y métodos finales. Entonces tengo todo lo que necesito para realizar mi trabajo.
Me gusta JMock porque puedes establecer expectativas. Esto es totalmente diferente de verificar si se llamó a un método encontrado en algunas bibliotecas simuladas. Usando JMock puedes escribir expectativas muy sofisticadas. Ver el jmock cheat-sheat .
Sí, Mockito es un gran marco. Lo uso junto con Hamcrest y Google Guice para configurar mis pruebas.
La mejor solución para burlarse es hacer que la máquina haga todo el trabajo con pruebas automatizadas basadas en especificaciones. Para Java, consulte ScalaCheck y el marco Reductio incluido en la biblioteca funcional de Java . Con los marcos de prueba automatizados basados en especificaciones, usted proporciona una especificación del método bajo prueba (una propiedad al respecto que debería ser verdadera) y el marco genera pruebas y objetos simulados, automáticamente.
Por ejemplo, la siguiente propiedad prueba el método Math.sqrt para ver si la raíz cuadrada de cualquier número positivo n al cuadrado es igual a n.
val propSqrt = forAll { (n: Int) => (n >= 0) ==> scala.Math.sqrt(n*n) == n }
Cuando llama propSqrt.check()
, ScalaCheck genera cientos de enteros y verifica su propiedad para cada uno, y también se asegura automáticamente de que los casos límite estén bien cubiertos.
Aunque ScalaCheck está escrito en Scala y requiere el compilador de Scala, es fácil probar el código Java con él. El framework Reductio en Functional Java es una implementación pura de Java de los mismos conceptos.
Mockito también ofrece la opción de métodos de apéndice, argumentos coincidentes (como anyInt () y anyString ()), verificando el número de invocaciones (times (3), atLeastOnce (), never ()) y más .
También descubrí que Mockito es simple y limpio .
Una cosa que no me gusta de Mockito es que no puede tropezar con métodos estáticos .
Comencé a usar simulacros a través de JMock, pero finalmente hice la transición para usar EasyMock. EasyMock era solo eso, más fácil, y proporcionaba una sintaxis que se sentía más natural. No he cambiado desde entonces.