5

Forse sto mostrando la mia mancanza di comprensione dell'input di dipendenza e dei test, ma non capisco come l'uso di dependency injection con classi che non implementano interfacce mi aiuti affatto con i test?Codice di test dipendente dalla libreria Enterprise anche se non fornisce interfacce?

Ad esempio, nella documentazione di Enterprise Library 5.0 si parla dell'utilizzo del contenitore Unity per creare istanze. Dice che questo aiuta "testabilità: è banale isolare le classi dalle dipendenze quando si utilizza lo stile di iniezione delle dipendenze". MSDN

Come si utilizza questo dispositivo di prova dell'unità? Il loro esempio ha un costruttore con parametri come classi piuttosto che interfacce:

public class TaxCalculator 
{ 
    private ExceptionManager _exceptionManager; 
    private LogWriter _logWriter; 

    public TaxCalculator(ExceptionManager em, LogWriter lw) 
    { 
    this._exceptionManager = em; 
    this._logWriter = lw; 
    } 
} 

risposta

9

Per rispondere alla domanda "Come verificare il codice libreria aziendale": non lo si. Testare le cose degli altri è compito di altre persone. Qualsiasi interfaccia o astrazione in Enterprise Library o qualsiasi altra libreria di terze parti esiste per i propri scopi di astrazione, non per il proprio.

Quello che devi fare è definire le tue interfacce che descrivono le esigenze della tua applicazione (registrazione, memorizzazione nella cache, crittografia, ecc.) E quindi scrivere adattatori che implementano le tue interfacce usando Enterprise Library (o altre librerie di terze parti) . Questa pratica è nota come Dependency Inversion Principle.

Per testare il proprio codice progettato in questo modo, per i test a livello di unità/componente si utilizza semplicemente Test Doubles per le interfacce definite dall'utente (ad es. IMyOwnLogger). Per testare gli adattatori che scrivi per adattarli alle librerie di terze parti, devi scrivere test di integrazione. Per verificare che funzioni tutti insieme, scriveresti test di accettazione che guidano l'app attraverso l'interfaccia utente o sottocutanea.

Per ulteriori informazioni su questa vista, controlla il mio articolo: "TDD Best Practices: Don't Mock Others".

+0

Ho cambiato il titolo per riflettere sul fatto che non voglio testare Enterprise Library ma il mio codice personale dipende da Enterprise Library. –

+0

Ho aggiornato la risposta per parlare esplicitamente di come testare il proprio codice alla luce delle dipendenze esterne. –

+0

Btw definisce le proprie interfacce che descrivono le esigenze della vostra applicazione (ad esempio la registrazione). La separazione dell'infrastruttura dal codice aziendale è ottima. Ma perdere le caratteristiche del framework, aggiungere un altro livello di astrazione, perdere ottimizzazioni e prestazioni, non è sicuramente positivo. –

4

È preferibile programmare contro l'astrazione anziché l'implementazione. Ma l'astrazione non è sempre l'interfaccia. Potrebbe essere una classe astratta.

public abstract class LogWriter 
{ 
    public abstract void Write(string message); 
} 

Quindi, non c'è nessun problema di creare finta di classe astratta:

Mock<LogWriter> logWriter = new Mock<LogWriter>(); 
TaxCalculator calc = new TaxCalculator(logWriter.Object); 

Se non fare unit test, non vedo alcun problema passare parametri non astratte, perché del principio YAGNI. Se non ho bisogno di un'altra implementazione di ExceptionManager, perché dovrei creare un'astrazione su di essa? Ma se faccio TDD, allora sicuramente avrò bisogno di almeno due implementazioni di classe. Uno vero e uno finto/mozzo.

Fare attenzione con service locator anti-pattern.

AGGIORNAMENTO: non è stato possibile riferirsi alle classi esistenti di Microsoft.Practices.EnterpriseLibrary (che non mi piace). Penso che questo sia un altro fallimento di progettazione del team di Microsoft.Practices. La classe ExceptionManager "sealed" che non implementa alcuna interfaccia/classe base uccide la testabilità.

+0

Le astrazioni nelle librerie di terze parti sono lì per i propri scopi, non per fornire un'astrazione da utilizzare. Inoltre, Enterprise Library è probabilmente lo scenario perfetto per l'utilizzo della parola chiave sealed. P & P ha sempre detto che non intendono utilizzare direttamente EL, ma per essere un esempio per scrivere codice. Non vogliono che le persone estendano le loro cose e poi si lamentino quando apportano un cambiamento di progettazione nelle versioni successive. –

+0

Quindi, pensi per es. ILog in log4net non deve fornirmi un'astrazione da usare? –

+0

Prendi questa affermazione come un'iperbole se vuoi. Diversi fornitori di software includono interfacce per diversi motivi. A volte le interfacce sono presenti come sottoprodotto della metodologia di test del fornitore. Altre volte ci possono essere più implementazioni su cui si basa un componente di livello superiore. Alcuni fornitori possono fornire interfacce come una giuntura nella speranza di consentire modifiche future al design senza modificare l'interfaccia pubblica. E sì, alcuni possono fornire interfacce pensando che sarà l'unica astrazione a dominarli tutti. Indipendentemente da ciò, non dovresti fare affidamento su di essi all'interno dei tuoi progetti. –

3

Fintanto che le classi non sono sealed, un quadro di simulazione esperto può creare una sottoclasse che agisce esattamente come un'implementazione di un'interfaccia fittizia. Ci sono più considerazioni da fare quando si dipende da classi concrete - i metodi sealed continueranno ad essere eseguiti sulla classe specificata, ecc. - ma in generale non è diverso da a seconda dell'interfaccia.

Problemi correlati