images icon example java junit testng jodatime

java - icon - ¿Es seguro usar DateTimeUtils.setCurrentMillisFixed en las pruebas?



line border java example (1)

Debe asegurarse de que DateTimeUtils.setCurrentMillisSystem() se invoque en el método tearDown . Para que una prueba no afecte a otra. TestNG debería invocar tearDown incluso si se produce una excepción en su prueba.

A menudo prefiero otra forma cuando quiero desacoplar una clase de System.currentTimeMillis(); . SystemClock un Clock interfaz y un SystemClock implementación como este:

public interface Clock { public long getCurrentTimeMillis(); } public class SystemClock implements Clock { public long getCurrentTimeMillis(){ return System.currentTimeMillis(); } }

Para las pruebas, es fácil crear un simulacro que devuelva un tiempo fijo en cada invocación o una serie de tiempos predefinidos.

Algunos podrían argumentar que es una ingeniería excesiva introducir una interfaz de este tipo para desacoplar solo un método y sería un impacto en el rendimiento. Pero, afortunadamente, tenemos un compilador JIT y como JIT sabe que solo se SystemClock clase SystemClock , sabe que no existe otra implementación (en este momento). En este supuesto, solo puede utilizar el método en línea.

Así que prefiero escribir el código de la manera que mejor se puede probar.

EDITAR

Con Java 8 es posible que desee utilizar la interfaz Supplier<Long> del Supplier<Long> .

Por ejemplo, en su código de cliente puede usar referencias de métodos.

public class SomeClass { private Supplier<Long> currentTimeMillisSupplier; public SomeClass(){ this(System::currentTimeMillis); } SomeClass(Supplier<Long> currentTimeMillisSupplier){ this.currentTimeMillisSupplier = currentTimeMillisSupplier; } }

El constructor predeterminado es para uso "normal", mientras que el otro constructor con ámbito de paquete se puede usar para pruebas unitarias. Simplemente coloque la clase de prueba en el mismo paquete.

También puede utilizar la interfaz del Clock , ya que es una @FunctionalInterface .

public class SomeClass { private Clock clock; public SomeClass(){ this(System::currentTimeMillis); } public SomeClass(Clock clock){ this.clock = clock; } }

Para probar el código dependiente del tiempo es bueno usar un patrón de reloj virtual

La idea es que obtengamos la hora actual no utilizando la new Date , sino desde un reloj que se puede burlar con el reloj virtual que devuelve el tiempo fijo predefinido.

Ahora en Java tenemos JodaTime con la clase DateTime y que permite establecer el tiempo de muestreo con

DateTimeUtils.setCurrentMillisFixed(today.getMillis());

Y reinicie la hora fija a una hora del sistema con:

DateTimeUtils.setCurrentMillisSystem();

Aquí hay un buen artículo sobre cómo usarlo con TestNG.

Ahora la pregunta!

Qué tan seguro es usar esta técnica con los métodos setUp y tearDown si establece globalmente el tiempo fijo en el contexto global durante el tiempo de ejecución de la prueba. Mientras lo obtenga, solo funcionará mientras no tengamos dos pruebas concurrentes con esta técnica ejecutándose en el mismo entorno en paralelo.