2012-06-01 7 views
15

Estoy usando JodaTime 2.1 y estoy buscando un código de prueba de unidad a unidad que realice operaciones de fecha/hora para asegurarse de que se comporta bien para todas las zonas horarias e independientemente de DST.¿Cómo escribo las pruebas unitarias para asegurarme de que mi código de fecha/hora funciona para todas las zonas horarias y con/sin horario de verano?

Específicamente:

  1. ¿Cómo puedo burlarse del reloj del sistema (por lo que no tiene que burlarse de todos los lugares en los que llamo new DateTime() para obtener la hora actual)
  2. ¿Cómo puedo hacer la misma para la zona horaria predeterminada?
+0

posible duplicado de [Hacer pruebas unitarias con fechas que pasan en todas las zonas horarias y con/sin DST] (http://stackoverflow.com/questions/10833948/make-unit-tests-with-dates-pass-in- all-time-zones-and-with-out-dst) – Caleb

+0

No es un duplicado; es un seguimiento. –

Respuesta

18

Puede utilizar un @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); 
    } 
} 

Puede utilizar la regla como la siguiente:

public class SomeTest { 

    @Rule 
    public UTCRule utcRule = new UTCRule(); 

    .... 
} 

Esto va a cambiar la zona horaria actual a UTC antes de cada prueba en SomeTest será ejecutado y lo hará restaurar la zona horaria predeterminada después de cada prueba.

Si desea comprobar varias zonas horarias, utilizar una regla como ésta:

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); 
    } 
} 

Poner todas las pruebas afectadas en una clase base abstracta AbstractTZTest y extenderla:

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 desea probar, necesitará otra clase:

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

Dado que se heredan los casos de prueba, eso es todo - sólo tiene que definir la regla.

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

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

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

2
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 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() 
{ 
//... 
} 
+0

No estoy seguro de que esto funcione independientemente del horario de verano. Por ejemplo, ahora mismo obtengo la zona horaria para "US/Pacific". Y ahora mismo, porque todavía estamos en horario de verano, recibo una compensación de -25200. Pero cuando volvamos a la hora estándar en noviembre, el mismo código devolverá -28800. ¿Estoy equivocado sobre eso? – Marvo

Cuestiones relacionadas