Moq: Unit testet eine Methode, die auf HttpContext basiert
Denken Sie an eine Methode in einem .NET-assembly:
public static string GetSecurityContextUserName()
{
//extract the username from request
string sUser = HttpContext.Current.User.Identity.Name;
//everything after the domain
sUser = sUser.Substring(sUser.IndexOf("\\") + 1).ToLower();
return sUser;
}
Möchte ich Ihnen diese Methode von einem unit test die Verwendung der Moq-framework. Diese assembly ist Teil eines webforms Lösung. Der unit-test sieht wie folgt aus, aber ich vermisse die Moq-code.
//arrange
string ADAccount = "BUGSBUNNY";
string fullADName = "LOONEYTUNES\BUGSBUNNY";
//act
//need to mock up the HttpContext here somehow -- using Moq.
string foundUserName = MyIdentityBL.GetSecurityContextUserName();
//assert
Assert.AreEqual(foundUserName, ADAccount, true, "Should have been the same User Identity.");
Frage:
- Wie kann ich mit Moq, vereinbaren Sie einen fake HttpContext-Objekt mit einem Wert wie "MyDomain\MyUser'?
- Wie assoziiere ich, dass fake mit meinem Anruf in meine statische Methode an
MyIdentityBL.GetSecurityContextUserName()
? - Haben Sie Vorschläge zur Verbesserung dieser code/Architektur?
InformationsquelleAutor der Frage p.campbell | 2009-07-31
Du musst angemeldet sein, um einen Kommentar abzugeben.
Webforms ist bekanntlich nicht testbar genau deshalb - eine große Menge code, können sich auf statische Klassen in der asp.net pipeline.
Um zu testen, diese mit Moq, müssen Sie umgestalten
GetSecurityContextUserName()
Methode zu verwenden, dependency injection mit einemHttpContextBase
Objekt.HttpContextWrapper
befindet sich inSystem.Web.Abstractions
die Schiffe mit .Net 3.5. Es ist ein wrapper für dieHttpContext
Klasse, und erstreckt sichHttpContextBase
und Sie können bauen eineHttpContextWrapper
nur so:Sogar besser, können Sie ein mock HttpContextBase und stellen Sie Ihre Erwartungen unter Verwendung von Moq. Einschließlich der Benutzer eingeloggt ist, etc.
In diesem Ort, können Sie nennen
GetSecurityContextUserName(mockContext.Object)
und Ihre Anwendung ist viel weniger gekoppelt, um die statische WebForms HttpContext. Wenn du gehst zu tun eine Menge von tests, die sich auf eine verspottet Zusammenhang ich sehr empfehlen,ein Blick auf Scott Hanselman ' s MvcMockHelpers Klassedie eine version für die Verwendung mit Moq. Es bequem mit der großen Menge des setup erforderlich. Und trotz des namens, Sie brauchen nicht, es zu tun mit MVC - ich nutze es erfolgreich mit webforms-Anwendungen, wenn ich kann umgestalten, Sie zu benutzenHttpContextBase
.InformationsquelleAutor der Antwort womp
Im Allgemeinen für ASP.NET unit-Tests, eher als der Zugriff auf HttpContext.Aktuelle sollten Sie eine Eigenschaft vom Typ HttpContextBase, deren Wert durch dependency injection (wie in der Antwort des Womp).
Jedoch für die Prüfung sicherheitsrelevante Funktionen würde ich empfehlen, mit Gewinde.CurrentThread.AUFTRAGGEBER (statt HttpContext.Aktuelle.Benutzer). Mit Thread.CurrentThread hat den Vorteil, auch wiederverwendbare, die außerhalb eines web-Kontext (und funktioniert auf die gleiche in einem web-Kontext, weil die ASP.NET framework legt immer beide Werte gleich).
Dann test-Thread.CurrentThread.AUFTRAGGEBER normalerweise verwende ich eine scope-Klasse stellt den Thread.CurrentThread um einen test Wert und wird dann zurückgesetzt auf entsorgen:
Dies passt gut mit dem standard .NET-security-Komponente -- in denen eine Komponente eine Schnittstelle bekannt (IPrincipal) und Ort (Thread.CurrentThread.AUFTRAGGEBER) - und wird mit jedem code, der korrekt verwendet/checks gegen den Thread.CurrentThread.Principal.
Basis Umfang-Klasse wäre so etwas wie die folgenden (anpassen wie notwendig für Dinge wie das hinzufügen von Rollen):
Andere alternative ist, anstelle der Verwendung der standard-security-Komponente, Standort, schreiben Sie Ihre app zu verwenden injiziert Sicherheit details, wie z.B. hinzufügen eines ISecurityContext Immobilie mit GetCurrentUser () - Methode oder ähnlichem, und verwenden Sie dann konsequent in Ihrer Anwendung-aber wenn Sie gehen, um dies in den Kontext einer web-Anwendung, dann könnte man genauso gut verwenden Sie die pre-built injiziert Kontext, HttpContextBase.
InformationsquelleAutor der Antwort Sly Gryphon
Haben Sie einen Blick auf diese
http://haacked.com/archive/2007/06/19/unit-tests-web-code-without-a-web-server-using-httpsimulator.aspx
Mit httpSimulator Klasse,Sie werden in der Lage sein zu gehen ein HttpContext-zu-handler
HttpSimulator das umzusetzen, was wir brauchen, um eine HttpContext-Instanz. So brauchen Sie nicht zu verwenden Moq hier.
InformationsquelleAutor der Antwort Davut Gürbüz
Außerdem können Sie moq wie unten
InformationsquelleAutor der Antwort PUG
Wenn Sie die CLR security-Modell (wie wir), dann müssen Sie einige abstrahierte Funktionen zum abrufen und festlegen der aktuellen Prinzipal-wenn Sie möchten, erlauben es, Tests durchzuführen, und verwenden Sie diese, Wann immer bekommen, oder die Einstellung der AUFTRAGGEBER. Dies ermöglicht Ihnen, get/set der AUFTRAGGEBER, wo immer relevant ist (in der Regel auf
HttpContext
im web und auf dem aktuellen thread woanders wie unit-tests). Dies würde so Aussehen:Wenn Sie einen benutzerdefinierten principal, dann können diese ziemlich gut integriert in die Schnittstelle, zum Beispiel unter
Current
nennen würdeGetCurrentPrincipal
undSetAsCurrent
nennen würdeSetCurrentPrincipal
.InformationsquelleAutor der Antwort Greg Beech
Dies ist nicht wirklich im Zusammenhang im mit Moq für unit-Tests, was, die Sie brauchen.
Generell haben wir bei der Arbeit haben eine mehrschichtige Architektur, in denen der code auf dem Präsentations-layer ist wirklich nur für die Anordnung der Dinge als auf der Benutzeroberfläche angezeigt. Diese Art von code ist nicht mit unit-tests. Der rest der Logik, die sich auf die business-Schicht, welche Sie nicht haben, um eine Abhängigkeit von der Präsentations-Schicht (D. H. UI-spezifischen Referenzen wie die HttpContext -) da die UI kann auch eine WinForms-Anwendung und nicht unbedingt eine web-Anwendung.
Auf diese Weise können Sie vermeiden, zu Durcheinander herum mit Mock-frameworks, die versuchen zu simulieren HttpRequests etc...obwohl es oft noch erforderlich sein kann.
InformationsquelleAutor der Antwort Juri