2010-08-19 7 views
5

(C#, servizio WCF, Rhino Mocks, MbUnit)Mocking senza iniezione

ho scritto test per il codice già in atto (sì lo so proprio nel modo sbagliato, ma è così che il suo elaborato sul mio attuale contratto). Ho fatto un po 'di ri-factoring per supportare il mocking - iniettando dipendenze, aggiungendo interfacce aggiuntive, ecc. - tutte hanno migliorato il design. Generalmente la mia esperienza di test è andata bene (esporre fragilità e migliorare il disaccoppiamento). Per qualsiasi oggetto, ho creato le maze dipendenti e questo si adatta bene a me e ha senso.

L'app ha essenzialmente 4 livelli fisici. Il database, un livello di repository per l'accesso ai dati, un servizio WCF connesso al repository tramite un livello di gestione (o logica aziendale), quindi dall'alto verso il basso appare come questo;

WCF gestori Repository Database

prova i gestori e lo strato repository è stato abbastanza semplice, beffardo le dipendenze con Rhino Mocks e iniettando loro nello strato in prova in quanto tale.

Il mio problema è nel test del livello WCF superiore. Dato che il mio servizio non ha il costruttore che mi permette di iniettare le dipendenze, non sono sicuro di come faccio a deridere una dipendenza durante il test dei metodi pubblici (ServiceContracts) sul servizio.

Spero che abbia senso e che ogni aiuto sia molto apprezzato. Sono a conoscenza di TypeMockIsolator ecc., Ma in realtà non voglio seguire questa strada sia per ragioni di budget che per altri motivi per cui non entrerò qui. Inoltre sono sicuro che ci sono molti "impilatori" intelligenti che hanno le informazioni di cui ho bisogno.

Grazie in anticipo.

risposta

2

C'è un motivo specifico che non puoi avere un costruttore sul vostro servizio?

In caso contrario, è possibile sovraccaricare i costruttori con un costruttore predefinito che esegue il cablaggio dei valori predefiniti e un costruttore parametrizzato con le proprie dipendenze. È ora possibile testare il sensore parametrico e affidarsi al ctor predefinito per creare l'istanza in produzione.

public MyService() : this(new DefaultDep1(), new DefaultDep2()) 
{ 
} 

public MyService(IDep1 d1, IDep2 d2) 
{ 
} 

Una soluzione migliore se si utilizza l'iniezione di dipendenza sarebbe quella di utilizzare il WCF IInstanceProvider interface per creare l'istanza di servizio e fornire le dipendenze necessarie attraverso tale punto di iniezione. Un esempio utilizzando Structure Map può essere trovato here.

+0

Grazie, sembra proprio il percorso che devo percorrere. Grazie per il link .. molto utile. –

+0

Grazie a tutti per il vostro aiuto. Mentre alcune delle risposte erano simili, ho scelto questo perché era succinto e indica una soluzione diretta al problema. Grazie ancora. –

0

È possibile rendere i servizi WCF uno strato sottile rispetto ai "gestori", in modo che abbiano poca o nessuna logica in essi che richiede test. Quindi non testarli e basta testare i manager. In alternativa, è possibile ottenere un effetto simile disponendo di un altro livello di "servizio" che contiene la logica dei servizi, che può essere testata, e far passare il codice WCF effettivo solo a quello.

+0

Ok .. grazie per quello .. Avevo pensato di fare qualcosa di simile ma stavo cercando di evitare di introdurre un livello. Ma bello averlo confermato come una possibilità. –

0

Il nostro servizio WCF ottiene tutte le sue dipendenze da un oggetto Factory e diamo al servizio un costruttore che prende IFactory. Quindi, se vogliamo scrivere un test che prende in giro una delle dipendenze, ad esempio un'IDipendenza, abbiamo solo bisogno di iniettare una fabbrica fittizia, che è programmata per restituire al servizio l'oggetto di IDependency deriso.

+0

Ho ragione nel dire che stai effettivamente introducendo un secondo costruttore solo per permetterti di configurarlo per il test? Non sto dicendo che non sono d'accordo, solo assicurandomi di capirlo. –

+0

Sì, non sto dicendo che è grandioso, è solo quello che usiamo e funziona OK. –

+0

Ho utilizzato questo approccio per abilitare il testing del codice legacy che non è stato progettato per questo. È un po 'brutto, ma è efficace. –

0

Se si utilizza un'inversione di controllo (IoC), come Unity, AutoFac o Castle Windsor, e un framework di derisione (ad esempio Moq, NMock, RhinoMocks) questo è abbastanza semplice purché si abbia il progetto giusto.

Per un buon tutorial su come farlo con RhinoMock e Windsor, dare un'occhiata a questo blog - http://ayende.com/Blog/archive/2007/02/10/WCF-Mocking-and-IoC-Oh-MY.aspx

+0

Ciao .. e grazie per l'articolo (buona lettura) ma penso che non sia proprio quello che sto cercando. L'articolo si riferisce a prendere in giro il servizio. Non voglio davvero deriderlo, voglio metterlo alla prova, ma ha delle dipendenze che devo prendere in giro e che non posso iniettare. (a meno che non mi sia sfuggito qualcosa) –

0

Se si utilizza Castle Windsor, dare un'occhiata al WCF facility, consente di utilizzare il costruttore non predefinito e inietta le dipendenze nei servizi, tra le altre cose.

+0

Non sono ... ma ho l'impressione che dovrei guardarlo :). Grazie per il consiglio. –