2010-08-11 19 views
14

Mi sto dando da fare per impostare i test unitari per alcune classi di utilità in un progetto su cui sto lavorando e una delle classi (contiene informazioni sulla licenza) ha un metodo questo fa una certa determinazione in base al tempo corrente.Gestione dei test delle unità con una condizione sull'ora corrente

ovvero la licenza contiene una data di scadenza e la stringa di licenza convalida quella data, ma la logica effettiva per verificare se la licenza è scaduta si basa sull'ora corrente.

public boolean isValid() 
{ 
    return isLicenseStringValid() && !isExpired(); 
} 

public boolean isExpired() 
{ 
    Date expiry = getExpiryDate(); 
    if(expiry == null) { 
     return false; 
    } 

    Date now = new Date(); 

    return now.after(expiry); 
} 

Quindi, io non sono sicuro di cosa fare, dal momento che la 'new Date()' cosa non è un criterio statico.

  1. Devo non si preoccupano di verificare 'isValid', e proprio test 'isLicenseStringValid()' e la 'getExpiryDate()' funzione separatamente?
  2. Ho appena usato una chiave di licenza nel test con una lunga scadenza pazzesca tale che avrò commutato i lavori prima che scada?
  3. Si tenta di prendere in giro "new Date()" con un metodo 'getCurrentTime()' in modo tale da poter simulare l'ora in cui è ora?

Che cosa fanno normalmente gli altri con i test che sono condizionati dal tempo?

+0

BTW, vedo un problema nel codice diverso logica Data: se (scadenza == null) { return false; } Non penso che dovresti restituire 'false' sul metodo' isExpired() 'se la data di scadenza è nulla. Per ulteriori informazioni, leggi - https://www.owasp.org/index.php/Fail_security – Garbage

+0

È un oggetto di licenza con due possibili modalità: 1. perpetuo senza data di scadenza (da cui sopra) 2. temporaneo con una data di scadenza quindi, è corretto che se non è impostata alcuna data di scadenza, non è scaduta. –

risposta

23

Definire definitivamente new Date().

Creare un'interfaccia Clock con un metodo getCurrentTime() o qualcosa di simile. In questo modo è possibile avere un FakeClock per il test e un SystemClock che utilizza System.currentTimeMillis() o qualsiasi altra cosa.

Ho fatto questo un numero di volte - ha funzionato molto bene. È logico anche - in modo efficace è necessario un "servizio orario corrente" in modo che dovrebbe essere iniettato come qualsiasi altra dipendenza.

+0

Grazie, sembra un po 'strano usare DI per cose che sembrano parte del linguaggio stesso, ma sembra che funzionerà. –

5

In genere inserisco un fornitore di data nel codice testato. Ciò aiuta anche se è necessario cambiare le convenzioni o altrimenti "correggere" il codice di test del tempo.

2

Utilizzare l'iniezione dipendente e iniettare un TimeProvider che fornisce un metodo getExpiryDate().

1

Tutti e tre gli approcci sono possibili:

  1. no prova: la via dell'uomo pigro
  2. utilizzare una licenza che non scade per secoli fino a quando hai lasciato il lavoro: coprire il mio modo ass
  3. utilizzare un mock per la data corrente, come ad esempio un TimeProvider: il modo perfezionista

mi piacerebbe andare per un comprimise: mi piacerebbe aggiungere la data corrente come parametro al metodo isExpired, e l'isValid metodo. Per il tuo codice di produzione dal vivo, aggiungi un semplice override di no-arg isValid() che chiama isValid(new Date()). Il tuo codice di test utilizza la versione che prende come parametro la data corrente.

+0

Questa opzione mi piace di più. Se la lingua supporta argomenti di default, lo rende un po 'più semplice. – elias

2

Se si sente l'astrazione TimeProvider/Clock è troppo fuori bordo perfezionista (che può benissimo essere il caso), prendere in considerazione questo invece

Fai getCurrentType protetto virtuale, quindi creare un decendant TestingProductionType del Tipo di produzione che contiene il codice hai postato.In questo tipo, eseguire l'override del metodo getCurrentType() per restituire un risultato deterministico. Nel test dell'unità, invece, crea un'istanza di questo TestingProductionType.

Viola, la dipendenza dell'ora corrente viene ora rimossa dai test dell'unità. L'unico codice di produzione che non è ora testato unitamente è un metodo con una sola riga che restituisce una nuova data(). Potrei vivere con quello.

Problemi correlati