Wie kann ein IoC-Container für Unit-Tests verwendet werden? Ist es nützlich, Mocks in einer riesigen Lösung (über 50 Projekte) mit IoC zu verwalten? Irgendwelche Erfahrungen? Gibt es C # -Bibliotheken, die sich gut für Unit-Tests eignen?
Wie kann ein IoC-Container für Unit-Tests verwendet werden? Ist es nützlich, Mocks in einer riesigen Lösung (über 50 Projekte) mit IoC zu verwalten? Irgendwelche Erfahrungen? Gibt es C # -Bibliotheken, die sich gut für Unit-Tests eignen?
Antworten:
Im Allgemeinen sollte ein DI-Container für Unit-Tests nicht erforderlich sein, da es bei Unit-Tests nur darum geht, die Verantwortlichkeiten zu trennen.
Stellen Sie sich eine Klasse vor, die Constructor Injection verwendet
public MyClass(IMyDependency dep) { }
In Ihrer gesamten Anwendung ist möglicherweise ein riesiges Abhängigkeitsdiagramm verborgen IMyDependency
, aber in einem Komponententest reduzieren Sie alles auf ein einziges Testdoppel .
Sie können dynamische Mocks wie Moq oder RhinoMocks verwenden, um das Test Double zu generieren, dies ist jedoch nicht erforderlich.
var dep = new Mock<IMyDependency>().Object;
var sut = new MyClass(dep);
In einigen Fällen kann es hilfreich sein , einen automatisch verspotteten Container zu haben, aber Sie müssen nicht denselben DI-Container verwenden, den die Produktionsanwendung verwendet.
Wie kann ein Ioc-Container für Unit-Tests verwendet werden?
IoC wird Programmierparadigmen durchsetzen, die das isolierte Testen von Einheiten (dh das Verwenden von Mocks) erleichtern: Verwendung von Schnittstellen, keine neuen (), keine Singletons ...
Die Verwendung des IoC-Containers zum Testen ist jedoch nicht unbedingt erforderlich. Er bietet lediglich einige Funktionen, z. B. das Einspritzen von Mocks, kann jedoch manuell durchgeführt werden.
Ist es nützlich, Mocks in einer riesigen Lösung (über 50 Projekte) mit IoC zu verwalten?
Ich bin mir nicht sicher, was Sie unter der Verwaltung von Mocks mit IoC verstehen. Wie auch immer, IoC-Container können normalerweise mehr als nur Mocks injizieren, wenn es um Tests geht. Und wenn Sie eine anständige IDE-Unterstützung haben, die Refactoring ermöglicht, warum nicht?
Irgendwelche Erfahrungen?
Ja, für eine große Lösung benötigen Sie mehr denn je eine nicht fehleranfällige und Refactoring-nachteilige Lösung (dh entweder über einen typsicheren IoC-Container oder eine gute IDE-Unterstützung).
In meinen Tests verwende ich häufig einen IoC-Container. Zugegeben, es handelt sich nicht um "Unit-Tests" im reinen Sinne. IMO Sie sind eher BDDish und erleichtern das Refactoring. Tests sind da, um Ihnen das Vertrauen in Refactor zu geben. Schlecht geschriebene Tests können wie das Eingießen von Zement in Ihren Code sein.
Folgendes berücksichtigen:
[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);
}
}
Beim Hinzufügen eines Bildes zur Galerie passieren verschiedene Dinge. Die Bildgröße wird geändert, eine Miniaturansicht wird erstellt und die Dateien werden auf AmazonS3 gespeichert. Durch die Verwendung eines Containers kann ich einfacher nur das Verhalten isolieren, das ich testen möchte. In diesem Fall handelt es sich um den persistierenden Teil.
Eine Auto-Mocking-Container-Erweiterung ist praktisch, wenn Sie diese Technik verwenden: http://www.agileatwork.com/auto-mocking-unity-container-extension/
Durch die Verwendung von Containern mit der Fähigkeit, nicht registrierte / unbekannte Dienste wie SimpleInjector aufzulösen , kann DryIoc (seine Mine) Mocks für noch nicht implementierte Schnittstellen zurückgeben.
Dies bedeutet, dass Sie mit der Entwicklung mit der ersten einfachen Implementierung und ihren verspotteten Abhängigkeiten beginnen und diese im weiteren Verlauf durch echte ersetzen können.