2010-10-06 14 views
22

Ho letto casi a favore e contro l'utilizzo del modello singleton. Un caso comune contro descrive le difficoltà nei test unitari con i singleton, ma non sono chiaro perché sia ​​così? Se il test unitario fa parte della build non potresti semplicemente fare riferimento al singleton e usarlo quando è necessario? (Sto pensando da una prospettiva java ma immagino che non dovrebbe importare)Perché è difficile testare un sistema che dipende dai singleton?

risposta

18

Un grande articolo su questo è Singletons are Pathological Liars. Questo descrive, usando un semplice esempio, perché testare usando i singletons è inaspettatamente difficile.

+4

Il collegamento è interrotto. – Emil

+2

Funziona bene qui. –

+0

Ottimo articolo, +1. L'unica cosa che vorrei che l'articolo cambiasse è l'esempio finale ... per me ha più senso che il metodo charge() sia sul CreditCardProcessor e che abbia preso la carta e l'ammontare come parametri :) – rmeador

2

This Google Techtalk fa un buon lavoro di descrizione dei problemi con singoletti e stato globale quando si tratta di test delle unità.

-2

Non ricordo di averlo mai letto, ma sospetto che il problema sia il fatto che è possibile creare solo uno. In alcuni casi, questo potrebbe non essere un problema, basta testarlo normalmente.

Ma cosa succede se si desidera creare e testarne uno diverso, magari con diversi parametri del metodo costruttore/fabbrica? Riavvia la JVM? Oppure crea il tuo singleton in modo che non sia il veramente un singleton e possa essere resettato? Non bene.

5

Se si fa riferimento a una classe singleton che esiste al di fuori della classe sottoposta a test, non si ha più un vero test di unità. Invece di testare una singola unità - la classe target - ora stai testando due unità: la classe target e il singleton.

C'è anche il fatto che gli oggetti singleton tendono ad avere uno stato. Affinché i test unitari siano ripetibili, è necessario eseguire il rollback di tali cambiamenti di stato al termine del test dell'unità. In alternativa, devi creare una versione fittizia del singleton che viene distrutta dopo l'esecuzione di ogni test. O aggiunge una notevole quantità di overhead, sia nel codice sorgente che nel tempo di esecuzione.

4

Poiché il singleton è una variabile globale OOPish. Fondamentalmente, tutte le funzioni che si basano sull'uso del singleton (direttamente o indirettamente) non sono garantite per essere deterministiche (cioè non ci si può aspettare che la funzione restituisca le stesse uscite per gli stessi ingressi T ogni esecuzione).

2

Singletons sono un problema per diversi motivi:

  • Si tratta di un caso particolare di un Service Locator, che fornisce un meccanismo per "farmi una di quelle" che non è necessariamente facile da ignorare quando necessario.
  • Forniscono un punto di ingresso per leggere o scrivere variabili globali. Il raggruppamento di tali variabili globali in un oggetto con una sola istanza accessibile a livello globale tramite il modello Singleton non comporta magicamente il blocco delle variabili globali.
  • Sono problemi anche per la manutenzione. Ad esempio, cosa succede quando smettono di essere un vero Singleton? Forse devi accedere a due database invece che al "database"?
4

TL; DR Lo stesso oggetto è condiviso tra tutti i test, che può diventare un dolore.

Se il singleton contiene uno stato e vengono eseguiti più test su di esso, l'ordinamento dei test può diventare un problema. Immagina un singleton "MailStore", che contiene un elenco di messaggi. Voglio scrivere un test unitario per elencare i messaggi e un altro per eliminarli.

Ovviamente se la "lista" viene eseguita prima dell'eliminazione, forse è ok. Se "cancella" viene eseguito prima della "lista", allora abbiamo difficoltà perché non c'è nulla da eliminare. (I risultati cambiano a seconda dell'ordine in cui vengono eseguiti i test.)

Problemi correlati