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?
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?
Risposte:
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.
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).
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/
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.