2009-08-10 6 views
2

Wir erstellen eine ASP.NET MVC-Site, und ich habe Schwierigkeiten, eine Verbindung zu definieren, um Unit-Tests am besten zu aktivieren (ich verwende 'Verbindung' generisch - es könnte eine Sitzung, eine Verbindung, ein Adapter oder irgendetwas sein anderer Typ von Datenkontext, der Transaktionen und Datenbankoperationen verwalten kann).Wo den Datenkontext (Adapter, Verbindung, Sitzung usw.) in MVC instanziieren?

Lassen Sie uns sagen, wir haben drei Klassen:

UserController 
UserService 
UserRepository 

In der Vergangenheit würden wir so etwas wie dies in einem Verfahren der Userservice tun:

Using (ISomeSession session = new SomeSession()) 
{ 
    session.StartTransaction(); 
    IUserRepository rep = new UserRepository(session); 
    rep.DoSomething(); 
    rep.Save(); 
    session.Commit(); 
} 

Allerdings war es nicht wirklich Möglich, Unit-Test, da die Abhängigkeit von SomeSession wurde nicht injiziert. Wenn wir jedoch D.I. Um die Abhängigkeit in den UserService zu injizieren, bleibt die Sitzung für die Lebensdauer des UserService hängen. Wenn es mehrere Dienste gibt, die vom UserController aus aufgerufen werden, kann jede Sitzung nur herumhängen, bis der UserController eine Garbage Collection durchführt.

Irgendwelche Gedanken, wie Sie das besser bewältigen können? Fehle ich etwas Offensichtliches?

bearbeiten

Sorry, wenn ich nicht klar war - Ich verstehe, dass ich Dependency Injection mit der Session/Datenkontext verwenden können, aber dann ist es über das Leben der Service-Klasse gehalten wird. Für länger laufende Aktionen/Methoden (d. H., Der Dienst wird durch einen Batch-Prozess aufgerufen), könnte dies zu vielen offenen Sitzungen führen, ohne dass ein anderer Grund als die Testbarkeit hinzugefügt wird.

+1

Wenn Sie mit einer echten Verbindung testen, werden keine Komponententests, sondern Integrationstests durchgeführt. – RichardOD

+0

Richard - das verstehe ich.Mein Punkt war, dass ich nicht wissen würde, wie man die Abhängigkeit auf die Klassenebene verschiebt, ohne die Verbindung während der gesamten Lebensdauer der Klasse am Leben zu halten (oder zumindest im Kontext aktiv) und nicht für eine kurze Zeit in der Using-Anweisung . Der Block "Verwenden" scheint viel sicherer zu sein, da er die Verbindung bei Bedarf öffnet und nach Abschluss schließt. –

Antwort

2

Wie RichardOD richtig festgestellt hat, können Sie keine Live-Datenbankverbindungen für Komponententests verwenden. Wenn Sie es tun, dann sind Sie Integrationstests.

Ich habe separate Implementierungen für meine Repository-Schnittstelle, ein reales Repository und ein falsches Repository für Komponententests. Das gefälschte Repository arbeitet an einer generischen Liste anstelle eines echten Datenkontextes. Ich benutze DI (mit Ninject, um Dinge bequemer zu machen, aber Sie können es genauso gut von Hand machen), um das richtige Repository zu injizieren.

Es gibt nur sehr wenige Instanzen, in denen ich Komponententests mit realen Verbindungen durchführe, aber das ist ein Komponententest für meine Repository-Klasse, nicht für Controller-, UI- oder Business-Layer-Objekte.

Bearbeiten: Mit dem Kommentar, den Sie hinzugefügt haben, denke ich, dass ich jetzt verstehe, was Sie tatsächlich gefragt haben. Lustig, du würdest etwas darüber fragen, da ich letzte Woche an demselben Thema gearbeitet habe :-)

Ich instanziiere den Datenkontext innerhalb eines sehr dünnen Wrappers und lege den Kontext in das HttpContext.Current.Items Dictionary. Auf diese Weise ist der Kontext global, jedoch nur für die aktuelle Anfrage.

Noch ist das Thema Ihrer Frage sehr irreführend. Sie haben gefragt, wo ein Datenkontext für Komponententests instanziiert werden soll, und die Antwort lautet normalerweise nicht. Meine Komponententests funktionieren immer noch auf gefälschten Repositories.

+0

Es ist in Ordnung, wenn Sie downvote, aber es wäre nett zu erklären, warum dies der Fall ist ... –

+0

Sorry ... Ich hätte antworten sollen. Ihre Antwort ist richtig, aber ich habe sie abgelehnt, weil sie meine Frage nicht beantwortet hat. Ich verstehe D.I. und wie man ein falsches Repository erstellt. Das Problem besteht darin, dass der Kontext außerhalb des Repositorys definiert ist und auch an andere Service/Repository-Klassen weitergegeben werden kann (d. H. Damit sie an der Transaktion teilnehmen können). Wenn wir den Kontext/die Verbindung in der Service-Instanz instanziieren (oder injizieren), entspricht die Lebensdauer des Kontexts der des Service ... im Wesentlichen erweitern wir den Verbindungsstatus weit über das typische "Verwenden (neuer Kontext) {...} ". –

+0

Ah, ok. Siehe meine Bearbeitung oben ... –

-2

Der einfachste Weg ist ein Connectionstring, den Sie in web.config für Entwicklung und Produktion definieren. Für Unittests definieren Sie es in app.config Ihres Testprojekts.

Verwandte Themen