2013-12-09 2 views
9

Come si esegue lo stub User.Identity.GetUserId() in ASP MVC 5 (Microsoft.AspNet.Identity) per un'unità test di un controller MVC5? GetUserId() è un'estensione, quindi non posso prenderlo in giro direttamente. E ho bisogno di assegnare l'Id prima del test. Sembra che devi creare un reclamo e assegnarlo a GenericIdentity. Ma sembra molto da fare per un test unitario. Conosci qualche alternativa?Come arrestare User.Identity.GetUserId() in ASP MVC 5 (Microsoft.AspNet.Identity)

+0

Vedere la mia risposta qui: http: // StackOverflow.com/a/39898952/2672291 – Haohmaru

risposta

12

Grazie molto molto per l'idea. Sto usando NSubstitute. Non ho né Microsoft Fakes né JustMock. Così ho finito affermazioni ripieno direttamente al GenericIdentity così ho potuto controllare il valore della UserId:

string username = "username"; 
string userid = Guid.NewGuid().ToString("N"); //could be a constant 

List<Claim> claims = new List<Claim>{ 
    new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", username), 
    new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", userid) 
}; 
var genericIdentity = new GenericIdentity(""); 
genericIdentity.AddClaims(claims); 
var genericPrincipal = new GenericPrincipal(genericIdentity, new string[] { "Asegurado" }); 
controllerContext.HttpContext.User = genericPrincipal; 
+0

Potrebbe per favore condividere il campione di lavoro per il beneficio di ciascuno. Sto anche lavorando sulla stessa linea. –

+0

IsAuthenticated è ancora falso, qualsiasi correzione per questo? – CularBytes

4

Pronto per un po 'di dolore?

Dipenderà molto da quale framework di derisione si sta utilizzando. Basandomi sul presupposto che tu stia usando Moq, sei un po 'sfortunato dal momento che Moq non fa un gran lavoro in questo senso. Il motivo è che Moq non può prendere in giro i metodi di estensione (in realtà è can ma non lo si/non dovrebbe volerlo fare :-))

Se si sta utilizzando un'altra struttura di simulazione come JustMock, il proprio chilometraggio potrebbe variare. Secondo lo this, è dannatamente più facile da vedere di quello che seguirà.

Il modo più semplice che ho trovato (che è ancora tutt'altro che facile) è quello di utilizzare Microsoft Fakes

La maggior parte delle cose nuove identità è scritto utilizzando le interfacce di estensione. Non posso per la vita di me capire perché hanno pensato che sarebbe stata una buona idea, ma ci sei.

Ecco cosa devi fare.

Inizia creando un assemblaggio falso per Microsoft.AspNet.Identity. È possibile farlo facendo clic con il pulsante destro del mouse sull'assieme e scegliendo "Aggiungi gruppo di falsi". Questo essenzialmente cammina l'assemblea e ha creato spessori e mozziconi per tutto ciò che trova lì. Quello che vuoi fare è shim la chiamata a GetUserId, .. e in realtà non è troppo difficile.

Quindi devi fare il solito beffardo di ControllerContext che sei, con i suoni abbastanza familiari.

Il seguente codice farà quello che stai cercando credo -

 using (var context = ShimsContext.Create()) 
     { 
      Microsoft.AspNet.Identity.Fakes 
       .ShimIdentityExtensions.GetUserIdIIdentity = 
      (i) => "Mr. T"; 

      var fakeHttpContext = new Mock<HttpContextBase>(); 
      var fakeIdentity = new GenericIdentity("User"); 
      var principal = new GenericPrincipal(fakeIdentity, null); 

      fakeHttpContext.Setup(t => t.User).Returns(principal); 

      var controllerContext = new Mock<ControllerContext>(); 
      controllerContext.Setup(t => t.HttpContext) 
       .Returns(fakeHttpContext.Object); 

      var sut = new HomeController(); 
      sut.ControllerContext = controllerContext.Object; 

      var result = sut.YourTestAction(); 
      Assert.True(result.WhatYouCareAbout); 
     } 

Naturalmente, non deve essere il signor T.

HTH

0

È possibile creare un principal falso e/o di identità che eredita dagli oggetti in MvcContrib.TestHelper.Fakes

allora si può fare qualcosa di simile:

 using (var userManager = _userManagerFactory.CreateUserManager()) 
     { 
      var userId = Guid.NewGuid().ToString(); 
      var result = userManager.CreateAsync(new IdentityUser() { Id = userId, UserName = "userName" }, "password").Result; 

      Assert.IsTrue(result.Succeeded, "failed to create user through usermanager"); 

      var fakePrincipal = new FakePrincipal(new FakeClaimIdentity(userId, "userName"), new[] { "SomeRole" }); 

      Assert.IsTrue(fakePrincipal.Identity.IsAuthenticated, "fake user did not come back authenticated"); 

     } 

La classe che ho usato per fare affermazioni che finta identità è questo:

using System.Collections.Generic; 
using System.Security.Claims; 
using MvcContrib.TestHelper.Fakes; 

namespace Tests.Unit.Fakes 
{ 
    public class FakeClaimIdentity : ClaimsIdentity 
    { 

     private readonly FakeIdentity _fakeIdentity; 


     public FakeClaimIdentity(string id, string userName) : base(userName) 
     { 
      _fakeIdentity = new FakeIdentity(userName); 
      base.AddClaims(new List<Claim> 
      { 
       new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", userName), 
       new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", id) 
      }); 
     } 

     public override bool IsAuthenticated 
     { 
      get { return _fakeIdentity.IsAuthenticated; } 
     } 

     public override string Name 
     { 
      get { return _fakeIdentity.Name; } 
     } 

     public override string AuthenticationType 
     { 
      get 
      { 
       return _fakeIdentity.AuthenticationType; 
      } 
     } 
    } 
} 

In questo modo è possibile testare anche la parte IsAuthenticated (se si cura della validità dell'identità).