Utilizzo di IoC per gli unit test


97

Come può essere utilizzato un contenitore IoC per gli unit test? È utile gestire i mock in una soluzione enorme (oltre 50 progetti) utilizzando IoC? Eventuali esperienze? Ci sono librerie C # che funzionano bene per usarlo negli unit test?


7
@Mark Seemann sarebbe troppo umile per farlo notare, ma se sei interessato a questa domanda, dovresti almeno essere a conoscenza di AutoFixture
Ruben Bartelink

1
C'è un bel discorso sulla relazione tra DI e derisione su Vimeo di Miguel Castro: vimeo.com/68390510
GregC

Risposte:


131

In generale, un contenitore DI non dovrebbe essere necessario per i test di unità perché il test di unità consiste nel separare le responsabilità.

Considera una classe che utilizza Constructor Injection

public MyClass(IMyDependency dep) { }

Nell'intera applicazione, potrebbe essere nascosto dietro un enorme grafico delle dipendenze IMyDependency, ma in uno unit test, lo appiattisci tutto in un singolo test Double .

Puoi usare mock dinamici come Moq o RhinoMocks per generare il Test Double, ma non è richiesto.

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

In alcuni casi, può essere utile avere un contenitore auto-mocking , ma non è necessario utilizzare lo stesso contenitore DI utilizzato dall'applicazione di produzione.


13
d'accordo ... a meno che un target di test non abbia un contenitore IoC come dipendenza, i tuoi test non dovrebbero averne bisogno ... rimuoverai la maggior parte del grafico a oggetti quando farai i tuoi unit test.
Anderson Imes,

4
@Mark Seemann Questo ha senso ... Ma per quanto riguarda i test di integrazione? Cioè, ho giocato con i test dell'interfaccia utente e ho affrontato situazioni in cui dovevo condividere la radice della composizione. Eventuali commenti?
Arnis Lapsa

5
@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 contenitore.
Mark Seemann

Fare riferimento a msdn magazine Test Double: download.microsoft.com/download/3/A/7/…
M.Hassan

18

Come può essere utilizzato un contenitore Ioc per i test unitari?

IoC applicherà paradigmi di programmazione che renderanno più semplici i test unitari (cioè usando mock): uso di interfacce, no new (), no singleton ...

Ma l'utilizzo del contenitore IoC per i test non è davvero un requisito, fornirà solo alcune funzionalità, ad esempio l'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 per gestire i mock utilizzando IoC. Ad ogni modo, i contenitori IoC di solito possono fare di più che iniettare mock quando si tratta di test. E se disponi di un supporto IDE decente che rende possibile il refactoring, perché non utilizzarlo?

Qualche esperienza?

Sì, su una soluzione enorme, hai bisogno più che mai di una soluzione non soggetta a errori e avversa al refactoring (ovvero tramite un contenitore IoC sicuro dei tipi o un buon supporto IDE).


17

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

Considera quanto segue:

[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 un'immagine alla galleria. L'immagine viene ridimensionata, viene generata una miniatura ei file vengono archiviati su AmazonS3. Utilizzando un contenitore posso isolare più facilmente solo il comportamento che voglio testare, che in questo caso è la parte persistente.

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


8
+1 per la frase "come versare cemento nel codice". Ho iniziato a usarlo tutto il tempo.
Andrew Shepherd

2

Utilizzando contenitori con la capacità di risolvere servizi non registrati / sconosciuti come SimpleInjector , DryIoc (la sua miniera) può restituire mock per interfacce non ancora implementate.

Ciò significa che puoi iniziare lo sviluppo con la prima semplice implementazione e le sue dipendenze fittizie e sostituirle con cose reali man mano che avanzi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.