java unit-testing timezone jodatime dst

java - ¿Cómo escribo las pruebas unitarias para asegurarme de que mi código basado en fecha/hora funcione para todas las zonas horarias y sin/sin DST?



unit-testing timezone (2)

Puedes usar una @Rule para esto. Aquí está el código para la regla:

import org.joda.time.DateTimeZone; import org.junit.rules.TestWatcher; import org.junit.runner.Description; public class UTCRule extends TestWatcher { private DateTimeZone origDefault = DateTimeZone.getDefault(); @Override protected void starting( Description description ) { DateTimeZone.setDefault( DateTimeZone.UTC ); } @Override protected void finished( Description description ) { DateTimeZone.setDefault( origDefault ); } }

Puedes usar la regla así:

public class SomeTest { @Rule public UTCRule utcRule = new UTCRule(); .... }

Esto cambiará la zona horaria actual a UTC antes de que se ejecute cada prueba en SomeTest y restaurará la zona horaria predeterminada después de cada prueba.

Si desea verificar varias zonas horarias, use una regla como esta:

import org.joda.time.DateTimeZone; import org.junit.rules.TestWatcher; import org.junit.runner.Description; public class TZRule extends TestWatcher { private DateTimeZone origDefault = DateTimeZone.getDefault(); private DateTimeZone tz; public TZRule( DateTimeZone tz ) { this.tz = tz; } @Override protected void starting( Description description ) { DateTimeZone.setDefault( tz ); } @Override protected void finished( Description description ) { DateTimeZone.setDefault( origDefault ); } }

Coloque todas las pruebas afectadas en una clase base abstracta AbstractTZTest y extiéndalo:

public class UTCTest extends AbstractTZTest { @Rule public TZRule tzRule = new TZRule( DateTimeZone.UTC ); }

Eso ejecutará todas las pruebas en AbstractTZTest con UTC. Para cada zona horaria que desee probar, necesitará otra clase:

public class UTCTest extends AbstractTZTest { @Rule public TZRule tzRule = new TZRule( DateTimeZone.forID( "..." ); }

Como los casos de prueba se heredan, eso es todo, solo necesita definir la regla.

De manera similar, puede cambiar el reloj del sistema. Use una regla que llame a DateTimeUtils.setCurrentMillisProvider(...) para simular que la prueba se ejecuta en un momento determinado y DateTimeUtils.setCurrentMillisSystem() para restaurar los valores predeterminados.

Nota: su proveedor necesitará una forma de marcar el reloj o todas las nuevas instancias de DateTime tendrán el mismo valor. A menudo adelanto el valor un milisegundo cada vez que se llama a getMillis() .

Nota 2: Eso solo funciona con joda-time. No afecta el new java.util.Date() .

Nota 3: Ya no puede ejecutar estas pruebas en paralelo. Deben ejecutarse en secuencia o uno de ellos probablemente restaure la zona horaria predeterminada mientras se ejecuta otra prueba.

Estoy usando JodaTime 2.1 y estoy buscando un patrón de código de prueba de unidad que realice operaciones de fecha / hora para asegurarme de que se comporte bien para todas las zonas horarias e independiente de DST .

Específicamente:

  1. ¿Cómo puedo burlarme del reloj del sistema (para no tener que burlarme de todos los lugares donde llamo a new DateTime() para obtener la hora actual)?
  2. ¿Cómo puedo hacer lo mismo para la zona horaria predeterminada?

for (String zoneId : DateTimeZone.getAvailableIDs()) { DateTime testedDate1; DateTime testedDate2; try { final DateTimeZone tz = DateTimeZone.forID(zoneId); // your test with testedDate1 and testedDate2 } catch (final IllegalArgumentException e) { // catching DST problem testedDate1 = testetDate1.plusHours(1); testedDate2 = testetDate2.plusHours(1); // repeat your test for this dates } }

Cambio para una sola prueba

DateTimeZone default; DateTimeZone testedTZ; @Before public void setUp() { default = GateTimeZone.getDefault(); DateTimeZone.setDefault } @After public void tearDown() { default = GateTimeZone.setDefault(); DateTimeZone.setDefault(testedTZ) } @Test public void test() { //... }