Mi lema para Java es "solo porque Java tiene bloques estáticos, no significa que deba usarlos". Bromas aparte, hay muchos trucos en Java que hacen que las pruebas sean una pesadilla. Dos de los que más odio son las Clases anónimas y los Bloques estáticos. Tenemos un montón de código heredado que hace uso de Static Blocks y estos son uno de los puntos molestos en nuestras pruebas de unidad de escritura. Nuestro objetivo es poder escribir pruebas unitarias para las clases que dependen de esta inicialización estática con cambios mínimos de código.Burlarse de bloques estáticos en Java
Hasta ahora mi sugerencia para mis colegas es mover el cuerpo del bloque estático a un método estático privado y llamarlo staticInit
. Este método puede ser llamado desde dentro del bloque estático. Para las pruebas unitarias, otra clase que dependa de esta clase podría fácilmente burlarse de staticInit
con JMockit para no hacer nada. Veamos esto en el ejemplo.
public class ClassWithStaticInit {
static {
System.out.println("static initializer.");
}
}
se cambiará a
public class ClassWithStaticInit {
static {
staticInit();
}
private static void staticInit() {
System.out.println("static initialized.");
}
}
Así que podemos hacer lo siguiente en un JUnit.
public class DependentClassTest {
public static class MockClassWithStaticInit {
public static void staticInit() {
}
}
@BeforeClass
public static void setUpBeforeClass() {
Mockit.redefineMethods(ClassWithStaticInit.class, MockClassWithStaticInit.class);
}
}
Sin embargo, esta solución también viene con sus propios problemas. No puede ejecutar DependentClassTest
y ClassWithStaticInitTest
en la misma JVM ya que realmente desea que el bloque estático se ejecute para ClassWithStaticInitTest
.
¿Cuál sería su forma de realizar esta tarea? ¿O alguna solución mejor, no basada en JMockit que creas que funcionaría más limpia?
No se puede burlar los métodos 'static' o' private' con EasyMock. Mover el cuerpo del inicializador estático es lo más parecido a una refactorización que podemos hacer por ahora. –
Si la clase bajo prueba tiene el método static init/private, desea que se invoque. No hay problema. Pero si se burla de la clase, no hay problema para simulacro fácil: no se llamará porque NO HAY IMPLEMENTACIÓN. Puedes burlarte de las interfaces públicas como si las cosas privadas no existieran. –