Dependency Injection lösen und unit-Tests
Ich versuche zu lernen, dependency injection und haben auf ein problem stoßen, wenn die unit-Tests der Anwendung.
Ich Schreibe eine Konsolenanwendung, und der container wird erstellt und initialisiert, die in Main(), es ist verfügbar als get-property
im Program.Container
, so dass überall in meiner Anwendung, die ich anrufen kann Program.Container.Resolve<..>()
.
Ich habe eine ServiceValidator Klasse wie folgt aus:
public class ServiceValidator
{
private readonly IConfiguration _configuration;
private readonly IService _service;
public ServiceValidator(IConfiguration configuration, IService service)
{
_configuration = configuration;
_service = service;
}
In einer anderen Klasse benutze ich
ServiceValidator serviceValidator = Program.Container.Resolve<ServiceValidator>();
serviceValidator.VerifyVersion();
Es ist der Aufruf zu Program.Container.Resolve
dass verursacht mir Probleme in der unit-test, wie es bisher nicht einrichten.
Ist das eine schlechte Praxis, um den Anruf zu lösen, die auf den container? Ich könnte die ServiceValidator Instanz in Main()
und übergeben Sie das Objekt um, aber das scheint dumm, wie es würde zu viele Parameter für die Objekte, die sich gerade übergeben, um Sie mit der nächsten Methode.
Also ich denke, es ist akzeptabel, rufen Beheben, die innerhalb einer Klasse, aber dann muss der Behälter so konfiguriert werden, dass der unit-test. Wie soll ich das machen, sollte ich den container verschieben an einen anderen Ort als das Programm Klasse? Was würden Sie empfehlen?
Wenn es darauf ankommt, bin ich mit Unity und C#
Dank 🙂
Du musst angemeldet sein, um einen Kommentar abzugeben.
Beim dependency-injection-alle Weg, dann werden Sie nicht brauchen, um passieren eine Vielzahl von Parametern für Objekte. Der Konstruktor für jedes Objekt sollte als Parameter nur die Abhängigkeiten, die es selbst verwendet direkt - es wird nicht das wissen über die transitiven Abhängigkeiten der direkten Abhängigkeiten.
So, wenn Sie eine Klasse X erfordert eine ServiceValidator, dann Klasse X ist ein Konstruktor parameter vom Typ ServiceValidator. Dann, wenn einige Klasse Y verwendet, der Klasse X, dann Klasse Y wird eine Konstruktor-parameter Art X. Beachten Sie, dass Y weiß nichts über ServiceValidator, so dass Sie nicht brauchen, um passieren die ServiceValidator von einer Klasse zur anderen - der einzige Ort, wo es verwendet wird, ist bei der Konstruktion der X, und das geschieht Häufig, indem ein DI-framework oder in nur einem Ort in einem hand-SCHRIFTLICHEN Werk.
Einige links für weitere Informationen:
Ich in der Regel, dass Anrufe Abhängigkeiten vom container in Orten wie Haupt-obwohl ich immer noch versuchen, Sie zu halten auf ein minimum. Was ich dann zu tun ist, konfigurieren Sie den container, in eine Initialisierungs-Methode einer Testklasse. Ich habe es initialisiert mit fake-Implementierungen für jede test-Klasse, die braucht, um den container.
Test-Klassen, die nicht einfach alles was der container initialisiert werden, sind dann in der Lage, es zu ignorieren und nicht die fakes. Ich verwende in der Regel spottet, dass in jenen Fällen, in.
Benutze ich auch die Microsoft Service Locator, so dass die Abhängigkeit, die ich zu mir nehme, ist auf etwas aus .NET Framework anstelle des auf einen bestimmten container. Dies ermöglicht es mir, die Straße hinunter alles, was ich will sogar ein Haus gebraut container.
Könntest du eine statische Klasse, die als Initialisierung für den container. So etwas wie BootStrapper.cs wäre in Ordnung. Sie können dann den Verweis auf die Klasse Methoden sowohl in Ihrem code und tests.
Gut, was Sie technisch tun, ist ein service-Standort in Ihrer Klasse.
Ich erinnere mich an das Lesen dieses Artikel eine Weile zurück:
http://martinfowler.com/articles/injection.html
Für meine Klassen, die ich nie versuchen, Lösen in Ihnen. Ich erstelle die Objekte über den container, wenn ich Sie brauche. Für Unit-Tests, die ich entweder einige mock-Bibliothek und stub Klassen.
Das problem liegt in der Tatsache, dass Sie versuchen, zu testen die Main-Methode. Diese Methode ist praktisch unmöglich, unit-test.
Ich würde behaupten, dass es das beste ist, nicht zu unit-testen Sie Ihre Main-Methode, weil: