L'iniezione di dipendenza è essenziale per il test dell'unità?

48

L'utilizzo di iniezione di dipendenza (DI) è essenziale per il test delle unità?

Non riesco a pensare ad un'altra alternativa per isolare il codice in modo che possa essere testato. Inoltre, tutti gli esempi che ho mai visto utilizzano questo modello. È perché è l'unica opzione praticabile o ci sono altre alternative?

    
posta Tom Squires 22.03.2012 - 16:34
fonte

7 risposte

36

DI rende molto più semplice il test delle unità. Ma puoi ancora scrivere test unitari senza DI. Un sacco di test unitari sono stati scritti già prima che DI si diffondesse. (Naturalmente, alcune di queste tecniche usate identiche o molto simili a DI senza sapere che ha un nome di fantasia: -)

Io stesso ho usato per es. interfacce e fabbriche molto prima di conoscere DI. Il nome effettivo della classe factory potrebbe essere stato letto da un file di configurazione o passato al SUT come argomento.

Un altro approccio sta usando singleton (o dati accessibili globalmente in generale). Sì, lo so che non è raccomandato da molti (incluso me stesso) in generale. Tuttavia può essere praticabile in situazioni specifiche, specialmente se il singleton contiene dati di configurazione statici che non sono specifici del test case, ma differiscono tra la produzione e l'ambiente di test. Ovviamente ha i suoi problemi noti, quindi DI è superiore se puoi usarlo. Ma spesso (ad esempio nei sistemi legacy) non puoi.

A proposito di questo, Lavorare efficacemente con il codice legacy descrive molti trucchi per ottenere il codice legacy coperto dai test . Molti di questi non sono belli e non sono pensati come una soluzione a lungo termine. Ma ti permettono di creare i primi preziosi test unitari a un sistema altrimenti non verificabile ... che ti consente di iniziare il refactoring, e alla fine (tra gli altri) introdurre DI.

    
risposta data 22.03.2012 - 16:37
fonte
51

Il disaccoppiamento è essenziale per il test dell'unità. DI è un ottimo modo per ottenere il disaccoppiamento.

    
risposta data 22.03.2012 - 17:22
fonte
9

A seconda delle tecnologie che stai utilizzando, puoi isolare le dipendenze senza usare DI. Ad esempio, nel mondo .NET, Moles consente di isolare le dipendenze senza il pattern DI.

Detto questo, credo che questi framework di isolamento siano scritti e pensati per situazioni nel tuo codice con dipendenze esterne (filesystem, database, ecc.). Cioè, il fatto che si possa fare questo non significa che lui o lei dovrebbe.

L'iniezione di dipendenza consente il test delle unità, ma consente anche la modifica del comportamento di un oggetto senza alterare il codice di quell'oggetto (principio aperto / chiuso). Quindi, non è solo un codice verificabile, ma un codice flessibile che risulta. In generale ho riscontrato una strong correlazione tra codice mantenibile / flessibile e codice verificabile.

    
risposta data 22.03.2012 - 16:38
fonte
4

No, DI non è essenziale per il test delle unità, ma aiuta molto.

Puoi utilizzare fabbriche o localizzatori e testare come faresti con DI (non altrettanto elegante e richiederebbe più impostazioni).

Inoltre, Mock Objects sarebbe importante nei sistemi legacy in cui molte chiamate sono delegate alle funzioni anziché alle dipendenze. (Anche gli oggetti simulati possono essere ampiamente utilizzati in una corretta configurazione)

Ci possono essere impostazioni in cui il test è quasi impossibile. Ma questo non è basato sull'utilizzo o meno dell'iniezione di dipendenza.

    
risposta data 22.03.2012 - 17:23
fonte
2

No , l'iniezione delle dipendenze non è essenziale per il test dell'unità.

L'iniezione delle dipendenze è utile se si ha una classe che ha bisogno di un'istanza di classe dipendente per eseguire alcuni processi secondari. Invece di DI puoi separare la logica di un metodo di business in una parte data-gethering (che non è testata dall'unità) e una parte di calcolo che può essere non testata.

Esempio (usando DI) Questa implementazione dipende da Dipendente, Account, ....

 bool hasPermissionToTranferMony(Employee employee, Account from, Account to, Money amount)
 {
     if (amount > 100 && imployee.isStudent())
        return false;
     if (to.getOwner().getFamiliyName() == Employee.getFamiliyName() && ...
        return false; // cannot transfer money to himself;
     ...
 }

Dopo la separazione di data-gethering e calcolo

 bool hasPermissionToTranferMony(Employee employee, Account from, Account to, Money amount)
 {
     return hasPermissionToTranferMony(employee.isStudent(), Employee.getFamiliyName(),  to.getOwner().getFamiliyName(), ....);
 }

 // the actualal permission calculation
 static bool hasPermissionToTranferMony(boolean isStudent, string employeeFamiliyName, string receiverFamiliyName, .....)
     if (amount > 100 && isStudent)
        return false;
     if (receiverFamiliyName == employeeFamiliyName && ...
        return false; // cannot transfer money to himself;
     ...
 }

La parte di calcolo può essere facilmente testata senza l'iniezione di dipendenza.

    
risposta data 04.05.2012 - 11:23
fonte
1
  • L'iniezione di dipendenza non è essenziale per il test dell'unità

  • L'inversione del controllo sull'altra mano è essenziale quando si desidera scambiare un'implementazione con un'altra.

risposta data 04.05.2012 - 11:41
fonte
0

Sì, ci sono alternative all'uso di DI per l'isolamento.

Un'alternativa è usare le fabbriche o un ServiceLocator che può essere configurato dai test per restituire oggetti simulati invece di quelli reali.

Un altro è usare un quadro di isolamento adatto o uno strumento di simulazione. Tali strumenti esistono per quasi tutti i linguaggi di programmazione moderni (almeno per Java, C #, Ruby e Python). Possono isolare una classe sottoposta a test dall'implementazione di altre classi / tipi, anche quando la classe testata istanzia direttamente le sue dipendenze.

    
risposta data 31.01.2014 - 21:32
fonte

Leggi altre domande sui tag