Frage

Ich versuche, Abhängigkeitsinjektion zu lernen und bin beim Testen der Anwendung auf ein Problem gestoßen.

Ich schreibe eine Konsolenanwendung und der Container wird in main () erstellt und initialisiert, sie ist als als erhältlich get-property in Program.Container, also überall in meiner Bewerbung kann ich anrufen Program.Container.Resolve<..>().

Ich habe eine Service -Validator -Klasse wie folgt:

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 Anruf zu Program.Container.Resolve Das verursacht mir Probleme im Unit -Test, da es nicht eingerichtet wurde.

Ist das eine schlechte Praxis, um Entschlossenheit im Container anzurufen? Ich könnte die ServiceValidator -Instanz in erstellen Main() Und übergeben das Objekt um, aber das erscheint dumm, da es viele Parameter für die Objekte verursachen würde, die gerade an die nächste Methode übergeben werden.

Ich denke, es ist akzeptabel, Resolve innerhalb einer Klasse anzurufen, aber dann muss der Container für den Unit -Test konfiguriert werden. Wie soll ich das tun, sollte ich den Container an einen anderen Ort als an die Programmklasse verschieben? Was würdest du empfehlen?

Wenn es wichtig ist, verwende ich Unity und C#

Vielen Dank :-)

War es hilfreich?

Lösung

Ist das eine schlechte Praxis, um Entschlossenheit im Container anzurufen? Ich könnte die ServiceValidator -Instanz in Main () erstellen und das Objekt umgeben, aber das scheint dumm zu sein, da es viele Parameter für die Objekte verursachen würde, die gerade an die nächste Methode übergeben werden.

Wenn Sie die Abhängigkeitsinjektion den ganzen Weg verwenden, müssen Sie nicht viele Parameter an Objekte übergeben. Der Konstruktor jedes Objekts sollte als Parameter nur diejenigen Abhängigkeiten haben, die er selbst direkt verwendet - es wird nicht über die transitiven Abhängigkeiten seiner direkten Abhängigkeiten informiert.

Wenn Sie also eine Klasse X haben, für die ein ServiceValidator erforderlich ist, verfügt die Klasse X über einen Konstruktorparameter vom Typ ServiceValidator. Wenn eine Klasse Y die Klasse X verwendet, hat die Klasse Y einen Konstruktorparameter vom Typ X. Beachten Sie, dass y y weiß nichts Über ServiceValidator, sodass Sie den ServiceValidator nicht von einer Klasse an eine andere weitergeben müssen - der einzige Ort, an dem er verwendet wird, ist beim Bau von X, und das wird oft durch ein DI -Framework oder an nur einem Ort in einem handgeschriebenen Ort erledigt Fabrik.

Einige Links für weitere Informationen:

Andere Tipps

Normalerweise erlaube ich Anrufe, Abhängigkeiten vom Container an Orten wie Main zu lösen, obwohl ich immer noch versuche, sie auf ein Minimum zu halten. Was ich dann mache, ist, den Container in einer Initialisierungsmethode einer Testklasse zu konfigurieren. Ich habe es mit gefälschten Implementierungen für jede Testklasse initialisiert, die den Container anrufen muss.

Testklassen, die nichts aufrufen, das den Container initiiert hat, können es dann ignorieren und die Fälschungen nicht verwenden. Normalerweise verwende ich in diesen Fällen Mocks.

Ich benutze auch das Microsoft Service Locator Damit die Abhängigkeit, die ich nehme, auf etwas aus dem .NET -Framework statt in einem bestimmten Container stammt. Dies ermöglicht es mir, die Straße hinunter zu benutzen, was ich auch für einen häuslichen Container möchte.

Sie können eine statische Klasse als Initialisierer für Ihren Container verwenden. So etwas wie Bootstrapper.cs würde in Ordnung sein. Sie können dann die Klassenmethoden sowohl in Ihrem Code als auch in Ihrem Code und Tests verweisen.

Nun, was Sie technisch tun, ist ein Serviceort in Ihrer Klasse.

Ich erinnere mich, dass ich diesen Artikel vor einiger Zeit vor einiger Zeit gelesen habe:

http://martinfowler.com/articles/injection.html

Für meine Klassen versuche ich nie, Lösung darin zu verwenden. Ich erstelle die Objekte über den Container, wenn ich sie brauche. Für Unit -Tests verwende ich entweder einige Scheinbibliothek und Stubklassen.

Das Problem liegt in der Tatsache, dass Sie versuchen, die Hauptmethode zu testen. Diese Methode ist praktisch unmöglich zu Unit -Tests.

Ich würde argumentieren, dass es am besten ist, Ihre Hauptmethode nicht zu testen, weil:

  • Der Schwerpunkt moderner Tests geht auf Design auf
  • Sie sollten die Abhängigkeit von der Konfiguration in Unit -Tests minimieren. Die Konfiguration kann mit Rauch- oder Integrationstests getestet werden.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top