Sono un test di unità in una classe in cui ho bisogno di un certo periodo di tempo prima di poter verificare i risultati. In particolare ho bisogno di x minuti per passare prima di poter dire se il test ha funzionato o meno. Ho letto che nei test unitari dovremmo testare l'interfaccia e non l'implementazione, quindi non dovremmo accedere a variabili private, ma oltre a mettere un sleep nel mio test unitario non so come testare senza modificare le variabili private.Come testare il passare del tempo in jUnit test senza accedere a variabili private?
Il mio test è impostato in questo modo:
@Test
public void testClearSession() {
final int timeout = 1;
final String sessionId = "test";
sessionMgr.setTimeout(timeout);
try {
sessionMgr.createSession(sessionId);
} catch (Exception e) {
e.printStackTrace();
}
DBSession session = sessionMgr.getSession(sessionId);
sessionMgr.clearSessions();
assertNotNull(sessionMgr.getSession(sessionId));
Calendar accessTime = Calendar.getInstance();
accessTime.add(Calendar.MINUTE, - timeout - 1);
session.setAccessTime(accessTime.getTime()); // MODIFY PRIVATE VARIABLE VIA PROTECTED SETTER
sessionMgr.clearSessions();
assertNull(sessionMgr.getSession(sessionId));
}
E 'possibile testare questa diversa modificando la variabile privata accessTime (tramite la creazione del setter setAccessTime o riflessione), o l'inserimento di un sonno nella prova di unità ?
EDIT 11-Aprile-2012
Sono in particolare cercando di verificare che il mio oggetto SessionManager cancella le sessioni dopo un determinato periodo di tempo è passato. Il database a cui mi sto connettendo interromperà le connessioni dopo un determinato periodo di tempo. Quando mi avvicino a quel timeout, l'oggetto SessionManager cancellerà le sessioni chiamando una procedura di "finalizzazione della sessione" sul database e rimuovendo le sessioni dal suo elenco interno.
L'oggetto SessionManager è progettato per essere eseguito in un thread separato. Il codice che sto testando si presenta così:
public synchronized void clearSessions() {
log.debug("clearSessions()");
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MINUTE, - timeout);
Iterator<Entry<String, DBSession>> entries = sessionList.entrySet().iterator();
while (entries.hasNext()) {
Entry<String, DBSession> entry = entries.next();
DBSession session = entry.getValue();
if (session.getAccessTime().before(cal.getTime())) {
// close connection
try {
connMgr.closeconn(session.getConnection(), entry.getKey());
} catch (Exception e) {
e.printStackTrace();
}
entries.remove();
}
}
}
La chiamata a connMgr (oggetto ConnectionManager) è un po 'contorto, ma sono in fase di refactoring codice legacy ed è quello che è in questo momento. L'oggetto Session memorizza una connessione al database e alcuni dati associati.
Una nota a margine: i test di unità in genere non devono testare nulla che funzioni in background (in thread separati). Quindi puoi dividere la logica e eseguirla in un altro thread. Il primo potrebbe quindi essere facilmente testato con i test unitari e il secondo con i test funzionali/di accettazione – zerkms
Il codice che stai testando chiama 'System.getCurrentTimeMillis()' (o qualcosa di equivalente come 'new Date()')? Se è così, questa è una sorta di anti-pattern di testabilità; vuoi delegare questo a una classe "sorgente temporale", che puoi iniettare. Quindi, puoi eseguire i test con una fonte temporale fittizia. Se puoi pubblicare la fonte che stai cercando di testare, posso aiutarti a capire come fare ciò che suggerisco. –
@DavidWallace - Ho appena assunto che GetInstance sia quella chiamata. JavaDocs conferma che il metodo getInstance di Calendar restituisce un oggetto Calendario i cui campi orari sono stati inizializzati con la data e l'ora correnti: ' – Gishu