2012-06-01 9 views
15

Utilizzo JodaTime 2.1 e sto cercando un codice di test unitario per il modello che esegue operazioni di data/ora per assicurarsi che si comporti bene per tutti i fusi orari e indipendente da DST.Come si scrivono i test unitari per assicurarsi che il mio codice basato su data/ora funzioni per tutti i fusi orari e con/out DST?

In particolare:

  1. Come posso prendere in giro l'orologio di sistema (quindi non c'è bisogno di prendere in giro tutti i luoghi dove io chiamo new DateTime() per ottenere l'ora corrente)
  2. Come posso fare lo stesso per il fuso orario predefinito?
+0

possibile duplicato di [Effettua test unitari con date pass in tutti i fusi orari e con/out DST] (http://stackoverflow.com/questions/10833948/make-unit-tests-with-dates-pass-in- zone di tutti i tempi-e-con-out-dst) – Caleb

+0

Non è un duplicato; è un seguito. –

risposta

18

È possibile utilizzare un @Rule per questo. Ecco il codice per la regola:

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

È possibile utilizzare la regola in questo modo:

public class SomeTest { 

    @Rule 
    public UTCRule utcRule = new UTCRule(); 

    .... 
} 

Questo cambierà il fuso orario corrente per UTC prima di ogni prova in SomeTest verrà eseguito e si ripristinare il fuso orario predefinito dopo ogni test.

Se si desidera controllare diversi fusi orari, utilizzare una regola come questa:

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

Mettere tutti i test interessate in una classe base astratta AbstractTZTest ed estenderlo:

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

Quello eseguirà tutti i test in AbstractTZTest con UTC. Per ogni fuso orario che si desidera verificare, avrete bisogno di un'altra classe:

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

Poiché i casi di test vengono ereditati, questo è tutto - basta per definire la regola.

In modo simile, è possibile spostare l'orologio di sistema. Utilizzare una regola che chiami DateTimeUtils.setCurrentMillisProvider(...) per simulare che il test venga eseguito in un determinato momento e DateTimeUtils.setCurrentMillisSystem() per ripristinare i valori predefiniti.

Nota: il provider richiederà un modo per far sì che l'orologio torni o tutte le nuove istanze DateTime abbiano lo stesso valore. Avanzando spesso il valore di un millisecondo ogni volta che viene chiamato getMillis().

Nota 2: funziona solo con joda-time. Non ha effetto su 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 
    } 
} 

Cambia singolo test

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

Non sono sicuro che funzionerà indipendentemente dall'ora legale. Ad esempio, ora sto ricevendo il fuso orario per "USA/Pacifico". E proprio ora, perché siamo ancora in DST, ottengo un offset di -25200. Ma quando torneremo all'ora solare di novembre, lo stesso codice restituirà -28800. Mi sbaglio? – Marvo

Problemi correlati