¿Cómo me burlo de User.Identity.GetUserId ()?

Estoy tratando de probar mi código unitario que incluye la línea:

UserLoginInfo userIdentity = UserManager.GetLogins(User.Identity.GetUserId()).FirstOrDefault(); 

Solo estoy atrapado en un momento porque no puedo obtenerlo:

 User.Identity.GetUserId() 

para devolver un valor He estado intentando lo siguiente en la configuración de mi controlador:

 var mock = new Mock(); mock.Setup(p => p.HttpContext.User.Identity.GetUserId()).Returns("string"); 

Pero da un error de “NotSupportedException no fue manejada por el código de usuario”. También he intentado lo siguiente:

 ControllerContext controllerContext = new ControllerContext(); string username = "username"; string userid = Guid.NewGuid().ToString("N"); //could be a constant List claims = new List{ 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("Andrew"); genericIdentity.AddClaims(claims); var genericPrincipal = new GenericPrincipal(genericIdentity, new string[] { }); controllerContext.HttpContext.User = genericPrincipal; 

Basado en algún código que encontré en stackoverflow, pero esto devuelve el mismo error “NotSupportedException no fue manejado por el código de usuario”.

Cualquier ayuda sobre cómo procedo sería apreciada. Gracias.

No puede configurar el método GetUserId porque es un método de extensión. En su lugar, deberá configurar el nombre en la propiedad IIdentity del usuario. GetUserId usará esto para determinar UserId.

 var context = new Mock(); var mockIdentity = new Mock(); context.SetupGet(x => x.User.Identity).Returns(mockIdentity.Object); mockIdentity.Setup(x => x.Name).Returns("test_name"); 

Consulte esto para obtener más información: http://msdn.microsoft.com/en-us/library/microsoft.aspnet.identity.identityextensions.getuserid(v=vs.111).aspx

No puede simular métodos de extensión directamente, por lo que su mejor opción es desglosar hasta llegar a las propiedades y métodos de los que depende el método de extensión que son susceptibles de burla.

En este caso, IIdentity.GetuUserId() es un método de extensión. Lo publicaría, pero la biblioteca no es actualmente de código abierto, por lo que tendrá que comprobar por sí mismo que GetUserId() depende de ClaimsIdentity.FindFirstValue() . Resulta que también es un método de extensión, pero depende de ClaimsIdentity.FindFirst() , que se marca como virtual . Ahora tenemos nuestra costura, entonces podemos hacer lo siguiente:

 var claim = new Claim("test", "IdOfYourChoosing"); var mockIdentity = Mock.Of(ci => ci.FindFirst(It.IsAny()) == claim); var controller = new MyController() { User = Mock.Of(ip => ip.Identity == mockIdentity) }; controller.User.Identity.GetUserId(); //returns "IdOfYourChoosing" 

Actualización: Me acabo de dar cuenta de que la solución que ApiControllers anteriormente solo funciona para ApiControllers derivados (como en, API web). La clase MVC Controller no tiene una propiedad de User configurable. Afortunadamente, es bastante fácil ingresar a través del Controller del ControllerContext para lograr el efecto deseado:

 var claim = new Claim("test", "IdOfYourChoosing"); var mockIdentity = Mock.Of(ci => ci.FindFirst(It.IsAny()) == claim); var mockContext = Mock.Of(cc => cc.HttpContext.User == mockIdentity); var controller = new MyController() { ControllerContext = mockContext }; 

Sin embargo, si todo lo que va a utilizar con el objeto User es obtener el Id. Del usuario, hay otro enfoque que funcionará para cualquier tipo de controlador y requiere mucho menos código:

 public class MyController: Controller //or ApiController { public Func GetUserId; //For testing public MyController() { GetUserId = () => User.Identity.GetUserId(); } //controller actions } 

Ahora, en lugar de llamar a User.Identity.GetUserId() cuando quiere el ID del usuario, simplemente llama a GetUserId() . Cuando necesita simular el ID del usuario en las pruebas, simplemente hágalo así:

 controller = new MyController() { GetUserId = () => "IdOfYourChoosing" }; 

Hay ventajas y desventajas para ambos enfoques. El primer enfoque es más completo y más flexible, y utiliza costuras que ya están presentes en los dos tipos de controlador, pero también es mucho más código y no lee casi tan bien. El segundo enfoque es mucho más limpio y el IMO más expresivo, pero es un código adicional para mantener, y si no usa la llamada de Func para obtener el Id del usuario, sus pruebas no funcionarán. Elija el que mejor funcione para su situación.

Esto funcionó para mí

usando fakeiteasy

  var identity = new GenericIdentity("TestUsername"); identity.AddClaim(new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "UserIdIWantReturned")); var fakePrincipal = A.Fake(); A.CallTo(() => fakePrincipal.Identity).Returns(identity); var _controller = new MyController { ControllerContext = A.Fake() }; A.CallTo(() => _controller.ControllerContext.HttpContext.User).Returns(fakePrincipal); 

Ahora puede obtener valores de esos métodos de extensión de IIdentity:

p.ej.

  var userid = _controller.User.Identity.GetUserId(); var userName = _controller.User.Identity.GetUserName(); 

Al ver el método GetUserId () con ILSpy, se muestra

 public static string GetUserId(this IIdentity identity) { if (identity == null) { throw new ArgumentNullException("identity"); } ClaimsIdentity claimsIdentity = identity as ClaimsIdentity; if (claimsIdentity != null) { return claimsIdentity.FindFirstValue(http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier); } return null; } 

Entonces GetUserId necesita el ” identificador de nombre ” de Claim