Comment puis-je écrire des tests unitaires pour m'assurer que mon code basé sur la date/heure fonctionne pour tous les fuseaux horaires et avec/sans DST?

j'utilise JodaTime 2.1 et je suis à la recherche d'un modèle à code de test unitaire qui effectue des opérations date/heure pour s'assurer qu'il se comporte bien pour tous les fuseaux horaires et indépendant de DST.

plus Précisément:

  1. Comment puis-je me moquer de l'horloge du système (pour ne pas avoir à me moquer de tous les endroits où j'appelle new DateTime() pour obtenir l'heure actuelle)
  2. Comment puis-je faire la même chose pour le fuseau horaire par défaut?
15
demandé sur Aaron Digulla 2012-06-01 12:12:56

2 réponses

Vous pouvez utiliser un @Rule pour cela. Voici le code de la règle:

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

Vous pouvez utiliser la règle comme ceci:

public class SomeTest {

    @Rule
    public UTCRule utcRule = new UTCRule();

    ....
}

ceci changera le fuseau horaire courant en UTC avant chaque test en SomeTest sera exécuté et restaurera le fuseau horaire par défaut après chaque test.

Si vous voulez vérifier plusieurs fuseaux horaires, l'utilisation d'une règle comme celle-ci:

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

mettez tous les tests affectés dans une classe de base abstraite AbstractTZTest et étendre:

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

exécuter tous les tests AbstractTZTest avec l'UTC. Pour chaque fuseau horaire que vous voulez tester, vous aurez besoin d'une autre classe:

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

puisque les cas de test sont hérités, c'est tout - vous avez juste besoin de définir la règle.

de la même manière, vous pouvez décaler l'horloge du système. L'utilisation d'une règle qui appelle DateTimeUtils.setCurrentMillisProvider(...) pour simuler que le test fonctionne à un certain moment et DateTimeUtils.setCurrentMillisSystem() pour restaurer les valeurs par défaut.

remarque: votre fournisseur besoin d'un moyen de faire de l'horloge ou le tout nouveau DateTime les instances auront la même valeur. J'ai souvent l'avance la valeur d'un millième de seconde à chaque fois getMillis() est appelée.

Note 2: cela ne fonctionne qu'avec joda-time. Il n'affecte pas les new java.util.Date().

22
répondu Aaron Digulla 2012-06-21 13:53:19
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
   }
}

Changer pour un seul 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()
{
//...
}
2
répondu Ilya 2012-06-04 12:04:16