2013-06-21 10 views
5

Come parte del codice Java, alcune attività devono essere eseguite domani in JUnit.Impostazione dell'ora e della data nel dispositivo di prova JUnit

Per esempio ci sono 3 compiti:

  • TASK1 - fatto
  • TASK2 - farlo domani
  • TASK3 - allora questo accadrà

Così come per ogni esigenza ho bisogno di imposta la data di oggi come domani in Java.

+0

Puoi mostrarci la fonte dei tuoi test unitari? – tbsalling

+0

Non ho bisogno di usare alcun framwork. Ho solo 3 compiti uno dopo l'altro come tre metodi calls.f1() -> f2() -> f3(). f2 può essere fatto domani e quindi nel risultato verrà chiamato f3. – hi5

+0

Vedere anche http://stackoverflow.com/questions/10652097/simulating-the-passing-of-time-in-unittesting – Raedwald

risposta

5

La chiave è estrarre l'idea di "qualcosa che può darti l'ora corrente" come dipendenza. (Insieme al fuso orario pertinente.)

Quindi invece di utilizzare new Date() o System.currentTimeMillis() si utilizza un'astrazione Clock. Per il codice di produzione si inserisce un'istanza di questo che utilizza l'orologio di sistema sottostante, ma per il test si utilizza un orologio falso che è possibile controllare in modo esplicito, per fare in modo che restituisca tutto ciò che si desidera.

(non è davvero chiaro esattamente quello che stai cercando di ottenere, ad essere onesti -. Ma questo approccio è il mio approccio standard per fare il tempo testabile)

9

La radice del problema è che l'orologio di sistema (cosa ti dà il tempo in un new Date()) non ti dà il tempo necessario per il test.

È possibile evitare questo problema introducendo un livello di riferimento indiretto. Invece di fare in modo che il tuo codice chieda direttamente all'API Java qual è l'ora corrente, hai il tuo codice chiedere a un oggetto Clock quale è l'ora. Nel programma reale l'implementazione Clock utilizza l'orologio di sistema. Per i tuoi test unitari usi un FakeClock, che dice a qualunque ora tu voglia. Dì al tuo codice cosa usare Clock usando l'iniezione di dipendenza . Devi scrivere tu stesso l'interfaccia Clock (o classe base astratta) e le sue implementazioni concrete.

Questo approccio richiede di modificare il codice esistente, quindi è più facile da testare o scrivere in primo luogo, quindi è più facile da testare. È uno dei trucchi dei test unitari.

Sto lavorando su un codice al momento sensibile al tempo. La mia interfaccia di clock è semplicemente

public interface Clock { 
    long getCurrentTime(); 
} 
3

Si consideri il seguente codice su GitHub: DateSupplier & & DateController. DateSupplier ha un metodo statico che restituisce la data corrente. DateController consente di modificare il valore di data restituito da DateSupplier in un ambiente di prova. È un JUnit Rule e si ripulisce da solo.

Questa è un'implementazione concreta delle idee Clock dalle altre due risposte. L'ho usato nei miei progetti per circa un anno con un buon successo. Ogni volta che ho il codice che farebbe new Date() io chiamo invece DateSupplier.getCurrentDate().

2

Considerare l'utilizzo di Joda Time, che sostituisce le classi di data e ora di Java.Fornisce

DateTimeUtils.setCurrentMillisFixed(long millis); 

che può essere utilizzato nei test.

+0

+1. Ho creato un'edizione di prova a tempo limitato e continuo a vedere Joda Time in SO per le risposte sul tempo. Questo è stato il problema che ha reso utile la modifica a Joda Time. Mi ci è voluta meno di un'ora per installarlo, cambiare il mio codice per usarlo e impostare il mio test con questo suggerimento. –

+0

La chiamata deve essere "DateTimeUtils.setCurrentMillisFixed (...)". Questa è la chiamata per impostare una data specifica. 'DateTimeUtils.setCurrentMillisSystem()' (senza parametri) imposta DateTime per utilizzare l'ora di sistema corrente. Vedi http://www.joda.org/joda-time/apidocs/index.html –

Problemi correlati