2009-09-23 4 views
92

Come può essere utilizzato un contenitore IoC per il test dell'unità? È utile gestire i mock in una soluzione enorme (oltre 50 progetti) utilizzando IoC? Qualche esperienza? Qualsiasi libreria C# che funzioni bene per utilizzarla nei test unitari?Utilizzo di IoC per il test dell'unità

+7

@Mark Seemann sarebbe troppo umile per farlo notare, ma se sei interessato a questa domanda, dovresti almeno essere a conoscenza di [AutoFixture] (http://autofixture.codeplex.com) –

+0

C'è una buona parla del rapporto tra DI e il mocking su Vimeo di Miguel Castro: https://vimeo.com/68390510 – GregC

risposta

118

In generale, un contenitore DI non dovrebbe essere necessario per il collaudo delle unità poiché il test dell'unità si basa esclusivamente sulla separazione delle responsabilità.

consideri una classe che utilizza Constructor iniezione

public MyClass(IMyDependency dep) { } 

Nella vostra intera applicazione, può essere che ci sia una dipendenza enorme grafico nascosta dietro IMyDependency, ma in una prova di unità, è appiattire il tutto ad un singolo Test Double.

È possibile utilizzare i mock dinamici come Moq o RhinoMocks per generare il Test Double, ma non è necessario.

var dep = new Mock<IMyDependency>().Object; 
var sut = new MyClass(dep); 

In alcuni casi, un auto-mocking container può essere bello avere, ma che non è necessario utilizzare lo stesso DI contenitore che l'applicazione di produzione utilizza.

+12

concordato ... a meno che un obiettivo di test abbia un contenitore IoC * come * una dipendenza, i tuoi test non dovrebbero averne bisogno .. si rimuoverà la maggior parte del grafico degli oggetti quando si eseguono i test unitari. –

+3

@ Mark Seemann Questo ha senso ... Ma per quanto riguarda i test di integrazione? Io, ho giocato con i test dell'interfaccia utente e ho affrontato situazioni in cui dovevo condividere la composizione root. Qualche commento? –

+3

@Arnis L .: Per i test di integrazione è meno importante. È possibile scegliere di utilizzare un contenitore DI per collegare i componenti, ma in tal caso è probabile che sia necessaria una configurazione diversa per il contenitore rispetto all'applicazione completa, a meno che non si esegua un test sottocutaneo o un test completo del sistema, nel qual caso puoi riutilizzare la configurazione dell'applicazione del Container. –

15

Come è possibile utilizzare un contenitore Ioc per il test dell'unità?

IOC applicherà paradigmi di programmazione che renderanno testing di unità di isolamento (cioè con mock) facile: uso di interfacce, nessun nuovo(), nessun singletons ...

Ma usando il contenitore IoC per il test non è davvero un requisito, ma fornirà solo alcuni servizi, ad es iniezione di mock ma potresti farlo manualmente.

È utile gestire i mock in una soluzione enorme (oltre 50 progetti) utilizzando IoC?

Non sono sicuro di cosa intendi gestendo i mock utilizzando IoC. In ogni caso, i contenitori IoC di solito possono fare molto di più che semplicemente fare l'iniezione di mock quando si tratta di test. E se hai un supporto IDE decente che rende possibile il refactoring, perché non usarlo?

Qualche esperienza?

Sì, su una soluzione enorme, è necessario più che mai una soluzione priva di errori e di refactoring-negativo (cioè attraverso un contenitore di oggetti sicuro di tipo o un buon supporto IDE).

13

Spesso nei miei test utilizzo un contenitore IoC. Certo, non sono "unit test" nel senso puro. IMO Sono più BDDish e facilitano il refactoring. I test sono lì per darti confidenza con il refactoring. Test scritti male possono essere come versare cemento nel codice.

Si consideri il seguente:

[TestFixture] 
public class ImageGalleryFixture : ContainerWiredFixture 
{ 
    [Test] 
    public void Should_save_image() 
    { 
     container.ConfigureMockFor<IFileRepository>() 
      .Setup(r => r.Create(It.IsAny<IFile>())) 
      .Verifiable(); 

     AddToGallery(new RequestWithRealFile()); 

     container.VerifyMockFor<IFileRepository>(); 
    } 

    private void AddToGallery(AddBusinessImage request) 
    { 
     container.Resolve<BusinessPublisher>().Consume(request); 
    } 
} 

Ci sono diverse cose che accadono quando si aggiunge una foto alla galleria. L'immagine viene ridimensionata, viene generata una miniatura e i file vengono archiviati su AmazonS3. Usando un contenitore posso isolare più facilmente solo il comportamento che voglio testare, che in questo caso è la parte persistente.

Un'estensione contenitore auto-beffardo è utile quando si utilizza questa tecnica: http://www.agileatwork.com/auto-mocking-unity-container-extension/

+7

+1 per la frase "come versare cementare nel tuo codice ". Ho iniziato a usarlo tutto il tempo. –

2

l'uso di contenitori con capacità di risolvere i servizi non registrati/Uknown come SimpleInjector, DryIoc (la sua miniera) può tornare prende in giro per le interfacce non ancora implementate .

Ciò significa che è possibile avviare lo sviluppo con la prima implementazione semplice e le sue dipendenze fittizie, e sostituirli con cose reali mentre si procede.