2013-03-14 13 views
23

My Unit-Tests für eine ApiController verwendet einige Methoden Helfer den Controller zu instanziiert:Set User-Eigenschaft für ein ApiController in Einheit Test

public static ResourcesController SetupResourcesController(HttpRequestMessage request, IResourceMetadataRepository repo, IUnitOfWorkService unitOfWorkService) 
{ 
    var config = new HttpConfiguration(); 
    var defaultRoute = config.Routes.MapHttpRoute(RouteNames.DefaultApi , "api/{controller}/{id}"); 
    var routeData = new HttpRouteData(defaultRoute, new HttpRouteValueDictionary { { "controller", "resources" } }); 

    var resourcesController = new ResourcesController(repo, unitOfWorkService) 
    { 
     ControllerContext = new HttpControllerContext(config, routeData, request), 
     Request = request 
    }; 
    resourcesController.Request.Properties.Add(HttpPropertyKeys.HttpRouteDataKey, routeData); 
    resourcesController.Request.Properties[HttpPropertyKeys.HttpConfigurationKey] = config; 

    // Compilation fail: The Property 'System.Web.Http.ApiController.User' has no setter. 
    resourcesController.User = myStubUserPrincipal; 

    return resourcesController; 
} 

Meine Frage ist: Wie kann der User-Eigenschaft für den Controller setzen?

Ich habe versucht:

request.Properties.Add("MS_UserPrincipal", myStubUserPrincipal); 

Aber das funktioniert auch nicht (die resourcesController.User Eigenschaft bleibt null).

Antwort

32

Setzen Sie die Thread.CurrentPrincipal, und das wird die User Eigenschaft in der Steuerung automatisch initialisiert.

Für Leute, die diese Antwort sehen, aber keine Ahnung haben, wie man CurrentPrincipal setzt.: This code wird von MSDN extrahiert.

Thread.CurrentPrincipal = new GenericPrincipal 
(
    new GenericIdentity("Bob", "Passport"), 
    new[] {"managers", "executives"} 
); 
+0

Dank Pablo! Scheint zu einfach, um wahr zu sein, aber ja; das Festlegen der Thread.CurrentPrincipal-Eigenschaft innerhalb meines Test-Setup-Codes hat den Trick gemacht! – JTech

+0

Großartig! Ich habe versucht, alles nachzuahmen/zu fälschen und das ist ein einfacher Weg, es zu tun. – Aligned

+3

Für Leute, die diese Antwort sehen, aber keine Ahnung haben, wie man CurrentPrincipal setzt. Dieser Code wird aus MSDN extrahiert. Thread.CurrentPrincipal = neues GenericPrincipal (neues GenericIdentity ("Bob", "Passport"), neues [] {"Manager", "Führungskräfte"}); http://msdn.microsoft.com/en-us/library/system.threading.thread.currentprincipal.aspx Fügen Sie dies zu Ihrer Antwort hinzu, wenn Sie möchten. – ruffen

8

Ein sauberere Weg IPrincipal und HttpRequestContext, zu verspotten wäre weg zum Beispiel unter Verwendung Moq:

var userMock = new Mock<IPrincipal>(); 
userMock.Setup(p => p.IsInRole("admin")).Returns(true); 
userMock.SetupGet(p => p.Identity.Name).Returns("tester"); 
userMock.SetupGet(p => p.Identity.IsAuthenticated).Returns(true); 

var requestContext = new Mock<HttpRequestContext>(); 
requestContext.Setup(x => x.Principal).Returns(userMock.Object); 

var controller = new ControllerToTest() 
{ 
    RequestContext = requestContext.Object, 
    Request = new HttpRequestMessage(), 
    Configuration = new HttpConfiguration() 
};