Ich habe eine ASP.NET MVC Core-Anwendung, für die ich Unit-Tests schreibe. Eine der Aktionsmethoden verwendet den Benutzernamen für einige Funktionen:
SettingsViewModel svm = _context.MySettings(User.Identity.Name);
was im Unit-Test offensichtlich fehlschlägt. Ich habe mich umgesehen und alle Vorschläge stammen aus .NET 4.5, um HttpContext zu verspotten. Ich bin sicher, es gibt einen besseren Weg, das zu tun. Ich habe versucht, IPrincipal zu injizieren, aber es wurde ein Fehler ausgegeben. und ich habe es sogar versucht (aus Verzweiflung, nehme ich an):
public IActionResult Index(IPrincipal principal = null) {
IPrincipal user = principal ?? User;
SettingsViewModel svm = _context.MySettings(user.Identity.Name);
return View(svm);
}
aber das warf auch einen Fehler. Konnte auch nichts in den Dokumenten finden ...
new Claim(ClaimTypes.Name, "1")
, Controller Verwendung von anzupassenuser.Identity.Name
; aber sonst ist es genau das, was ich erreichen wollte ... Danke schon!User.FindFirstValue(ClaimTypes.NameIdentifier);
die Benutzer-ID für ein Objekt festgelegt, das ich erstellt habe, und ist fehlgeschlagen, weil der Principal null war. Das hat das für mich behoben. Danke für die tolle Antwort!In früheren Versionen haben Sie möglicherweise
User
direkt auf dem Controller eingestellt, was einige sehr einfache Komponententests ermöglichte.Wenn Sie sich den Quellcode für ControllerBase ansehen, werden Sie feststellen, dass der aus
User
extrahiert wirdHttpContext
.und die Steuerung greift auf die
HttpContext
Via zuControllerContext
Sie werden feststellen, dass diese beiden Eigenschaften schreibgeschützt sind. Die gute Nachricht ist, dass die
ControllerContext
Eigenschaft es ermöglicht, ihren Wert so einzustellen, dass Sie sich darauf einlassen.Das Ziel ist es also, an dieses Objekt zu gelangen. In Core
HttpContext
ist abstrakt, so ist es viel einfacher zu verspotten.Angenommen, ein Controller wie
Mit Moq könnte ein Test so aussehen
quelle
Es besteht auch die Möglichkeit, die vorhandenen Klassen zu verwenden und nur bei Bedarf zu verspotten.
quelle
In meinem Fall musste ich Gebrauch machen
Request.HttpContext.User.Identity.IsAuthenticated
,Request.HttpContext.User.Identity.Name
und einige Business - Logik sitzt außerhalb des Controllers. Ich konnte eine Kombination aus Nkosis, Calins und Pokes Antwort verwenden:quelle
Ich würde versuchen, ein abstraktes Fabrikmuster zu implementieren.
Erstellen Sie eine Schnittstelle für eine Factory, um Benutzernamen bereitzustellen.
Geben Sie dann konkrete Klassen an, eine, die bereitstellt
User.Identity.Name
, und eine, die einen anderen fest codierten Wert bereitstellt , der für Ihre Tests geeignet ist.Sie können dann die entsprechende konkrete Klasse verwenden, abhängig von der Produktion im Vergleich zum Testcode. Vielleicht möchten Sie die Factory als Parameter übergeben oder anhand eines Konfigurationswerts zur richtigen Factory wechseln.
quelle