2012-02-14 15 views
20

Nel mio codice ho qualcosa di simile:java: come simulare Calendar.getInstance()?

private void doSomething() { 
    Calendar today = Calendar.getInstance(); 
    .... 
} 

Come faccio a "finto" nel mio test JUnit per restituire una data specifica?

+1

Quella linea non potrebbe essere la compilazione! – adarshr

+0

È 'today' un membro della classe (campo) o una variabile locale all'interno di un metodo? –

+0

variabile locale all'interno di un metodo – Randomize

risposta

14

Per quanto vedo io avete tre opzioni ragionevoli:

  1. iniettare l'istanza Calendar in qualsiasi metodo/classe di impostare quel giorno.

    private void method(final Calendar cal) { Date today = cal.getTime(); }

  2. Utilizzare JodaTime anziché Calendar. Questa è meno un'opzione e più un caso di un suggerimento dato che JodaTime renderà la tua vita molto più semplice. Dovrai comunque iniettare questa volta il metodo.

    DateTime dt = new DateTime();

    Date jdkDate = dt.toDate();

  3. Wrap Calendar all'interno di alcuni un'interfaccia che consente di procurarsi la volta. Quindi prendi semplicemente in giro quell'interfaccia e ottieni che restituisca una costante Date.

    Date today = calendarInterfaceInstance.getCurrentDate()

+3

La classe 'DateTimeUtils' di Joda Time ha metodi statici che impostano l'ora corrente per tutti gli altri oggetti Joda Time. Questo è molto utile per impostare il tempo per un certo momento, ad esempio per il test. – Jesper

+0

@Jesper - Sì, questo è vero ed è un buon punto che ho dimenticato di menzionare – BeRecursive

+1

Grazie ragazzi. Ho seguito i tuoi suggerimenti e mi sono trasferito a JodaTime. BTW risolve facilmente il problema con qualcosa di simile: DateTimeUtils.setCurrentMillisFixed (new DateTime (2012, 2, 14, 13, 43, 21) .getMillis()); – Randomize

9

Non prendere in giro, ma introdurre un metodo che è possibile prendere in giro per ottenere le date. Qualcosa di simile a questo:

interface Utility { 

    Date getDate(); 
} 

Utilities implements Utility { 


    public Date getDate() { 

     return Calendar.getInstance().getTime(); 
    } 

} 

Poi si può iniettare questo nella vostra classe o semplicemente usare una classe di supporto con un mazzo di metodi statici, con un metodo di carico per l'interfaccia:

public class AppUtil { 

    private static Utility util = new Utilities(); 

    public static void load(Utility newUtil) { 

     this.util = newUtil; 
    } 

    public static Date getDate() { 

     return util.getDate(); 
    } 

} 

Poi nell'applicazione codice:

private void doSomething() { 
    Date today = AppUtil.getDate(); 
    .... 
} 

È quindi possibile caricare un'interfaccia fittizia nei metodi di test.

@Test 
public void shouldDoSomethingUseful() { 
    Utility mockUtility = // .. create mock here 
    AppUtil.load(mockUtility); 

    // .. set up your expectations 

    // exercise the functionality 
    classUnderTest.doSomethingViaAPI(); 

    // ... maybe assert something 

} 

Vedi anche Should you only mock types you own? e Test smell - everything is mocked

2

Scrivi una classe chiamata DateHelper con un metodo che restituisce getCalendarCalendar.getInstance(). Rifatta la classe che stai testando in modo che abbia una variabile membro di tipo DateHelper e un costruttore che inietta quella variabile membro. Utilizzare quel costruttore nel test per iniettare una simulazione di DateHelper, in cui è stato stubato getCalendar per restituire una data nota.

9

Si può prendere in giro usando PowerMock in combinazione con Mockito:

in cima alla vostra classe:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ClassThatCallsTheCalendar.class}) 

La chiave del successo è che devi mettere la classe in cui si utilizza Calendar in PrepareForTest invece di Calendar stesso perché è una classe di sistema. (Ho dovuto personalmente a cercare molto prima ho trovato questo)

Poi il beffardo stesso:

mockStatic(Calendar.class); 
when(Calendar.getInstance()).thenReturn(calendar); 
+0

quali dipendenze includi per far funzionare il metodo mockStatic()? –

+0

Scusa avrei dovuto dirlo. Ho usato import static per importare il metodo mockStatic di PowerMockito. Vedi questa dipendenza per powermock mockito: http://mvnrepository.com/artifact/org.powermock/powermock-api-mockito2/1.6.6 – GoGoris

6

Utilizzando Mockito e PowerMockito:

Calendar endOfMarch = Calendar.getInstance(); 
endOfMarch.set(2011, Calendar.MARCH, 27); 
PowerMockito.mockStatic(Calendar.class); 
Mockito.when(Calendar.getInstance()).thenReturn(endOfMarch); 

Fare riferimento al link per il codice completo.

0

Per chi segue modello MVP beffardo calendario è un pezzo di torta:

  1. In un presentatore creare un metodo che restituisce esempio calendario:

    public Calendar getCurrentTime() { 
         return Calendar.getInstance();  
        } 
    
  2. Secondo lei (Attività, Frammento ecc.) Accedi al calendario con l'aiuto del relatore:

    Calendar calendar = mPresenter.getCurrentTime(); 
    // do whatever you want 
    
  3. Nei vostri test che fai:

    // create a dummy calendar 
    Calendar mockCalendar = ... 
    // You've already mocked your Presenter, haven't you? 
    when(mMockPresenter.getCurrentTime()).thenReturn(mockCalendar); 
    // here you are!