2014-06-11 13 views
5

Ich versuche, die User.Identity in meinem Api-Controller-Test zu verspotten.Unit Test Web Api 2 Mock Benutzer

Das ist mein api Methode:

[Route(Urls.CustInfo.GetCustomerManagers)] 
    public HttpResponseMessage GetCustomerManagers([FromUri]int groupId = -1) 
    { 
     var user = User.Identity.Name; 
     if (IsStaff(user) && groupId == -1) 
     { 
      return ErrorMissingQueryStringParameter; 
     } 
     ... 
    } 

Ich folgte dem Vorschlag in diesem Beitrag: Set User property for an ApiController in Unit Test die User-Eigenschaft einzustellen.

Dies ist mein Test:

[TestMethod] 
    public void User_Without_Group_Level_Access_Call_GetCustomerManagers_Should_Fail() 
    { 
     Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("Bob", "Passport"), new[] {"managers"}); 
     var response = m_controller.GetCustomerManagers(); 

     Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode); 
    } 

Aber wenn der Test durchgeführt wird, ist die User-Eigenschaft immer null.

Ich habe sogar versucht, die Zeile für die Einstellung der CurrentPrincipal in die API-Methode kurz vor dem Aufruf von User.Identity zu verschieben, aber es ist immer noch null.

Was mache ich falsch? Wenn dieser Ansatz für Web API 2 nicht funktioniert, was ist der beste Weg, um die Benutzereigenschaft zu simulieren?

Danke!

Antwort

13

Sie können die Benutzer in ControllerContext.RequestContext.Principal gesetzt:

controller.ControllerContext.RequestContext.Principal = new GenericPrincipal(new GenericIdentity("Bob", "Passport"), new[] {"managers"}); 

Oder eine Kurz Äquivalent:

controller.User = new GenericPrincipal(new GenericIdentity("Bob", "Passport"), new[] {"managers"}); 
+1

Nachdem der Principal auf diese Weise festgelegt wurde, ist die UserId nicht festgelegt. Ich brauche es einzustellen, weil die Logik in meinem System-zu-Test auf der Benutzer-ID basiert. Z.B. 'User.Identity.Name' ist gefüllt (" Bob "), aber nicht" User.Identity.GetUserId() ". – Bart

+0

@Bart hast du das jemals gelöst? –

+0

@Ben Hall Es ist schon eine Weile her, aber ich glaube nicht, dass ich es getan habe. Ich denke, meine Problemumgehung bestand nur darin, die Logik zu ändern, um 'UserName' anstelle von' UserId' zu verwenden. – Bart

4

Für eine einfachere Unit-Test von Web-API-2, Sie MyTested.WebApi verwenden können. Hier ist ein Beispiel mit authentifizierten Benutzer:

MyWebApi 
    .Controller<WebApiController>() 
    .WithAuthenticatedUser(user => user.WithUsername("NewUserName")) 
    .Calling(c => c.SomeAction()) 
    .ShouldReturn() 
    .Ok(); 
0

schaffe ich habe etwas, um tatsächlich eingestellt zu lösen für GetUserID zurückzukehren() in Bezug auf einen Benutzernamen in der Antwort im Gegensatz mit den meisten Stimmen. Entschuldigung, dass Oyu von meiner Verwendung von FakeItEasy auf das Mock-Tool Ihrer Wahl übersetzen muss.

Claim claim = new Claim("", userId); 
ClaimsIdentity fakeClaimsIdentity = A.Fake<ClaimsIdentity>(); 
A.CallTo(() => fakeClaimsIdentity.FindFirst(A<string>.Ignored)).Returns(claim); 

IPrincipal fakeIPrincipal = A.Fake<IPrincipal>(); 
A.CallTo(() => fakeIPrincipal.Identity).Returns(fakeClaimsIdentity); 

var controller = new AuthorisedServicesController() 
{ 
     User = fakeIPrincipal 
}; 

jedoch eine bessere Lösung (wenn ich den Code wieder schrieb) zu abstrahieren wäre der eigentliche Code Aufruf GetUserID so kann ich dann ein Objekt injizieren, die diesen Anruf machen, ist dies leicht mockable. Ein bisschen wie eine Fabrik.