webapi visual unit test studio net framework asp asp.net asp.net-mvc mocking

asp.net - visual - unit test webapi



Mocking User.Identity en ASP.NET MVC (6)

Cambié el entorno de desarrollo global.asax y Web.Config para usar FormsAuth para forzar a un usuario específico. El nombre de usuario usa el mismo formato de WindowsAuth. Ver:

public override void Init() { base.Init(); this.PostAuthenticateRequest += new EventHandler(MvcApplication_PostAuthenticateRequest); } void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e) { FormsAuthentication.SetAuthCookie("Domain//login", true); }

La autenticación de Windows o de formularios comparte los mismos patrones de inicio de sesión .

La aplicación funcionará con autenticación de Windows y autenticación de formulario.

Necesito crear pruebas unitarias para un sitio web ASP.NET MVC 2.0. El sitio usa Autenticación de Windows.

He estado leyendo sobre la necesidad de burlarse del contexto HTTP para el código que trata con el HttpContext. Siento que estoy empezando a manejar el patrón DI también. (Proporcione a la clase un atributo de tipo IRepository y luego pase un objeto Repository cuando cree una instancia del controlador).

Lo que no entiendo, sin embargo, es la forma correcta de simular el objeto principal de Windows disponible a través de User.Identity. ¿Es esto parte del HttpContext?

¿Algún cuerpo tiene un enlace a un artículo que demuestra esto (o una recomendación para un libro)?

Gracias,

Trey Carroll


He usado IoC para abstraer esto con cierto éxito. Primero definí una clase para representar al usuario actualmente conectado:

public class CurrentUser { public CurrentUser(IIdentity identity) { IsAuthenticated = identity.IsAuthenticated; DisplayName = identity.Name; var formsIdentity = identity as FormsIdentity; if (formsIdentity != null) { UserID = int.Parse(formsIdentity.Ticket.UserData); } } public string DisplayName { get; private set; } public bool IsAuthenticated { get; private set; } public int UserID { get; private set; } }

Se necesita una IIdentity en el constructor para establecer sus valores. Para las pruebas unitarias, puede agregar otro constructor para permitirle omitir la dependencia de IIdentity .

Y luego uso Ninject (elija su contenedor IoC favorito, no importa), y creé un enlace para IIdentity como tal:

Bind<IIdentity>().ToMethod(c => HttpContext.Current.User.Identity);

Luego, dentro de mi controlador, declaro la dependencia en el constructor:

CurrentUser _currentUser; public HomeController(CurrentUser currentUser) { _currentUser = currentUser; }

El contenedor IoC ve que HomeController toma un objeto CurrentUser y el constructor CurrentUser toma un IIdentity . Resolverá las dependencias automáticamente, y ¡listo! Su controlador puede saber quién es el usuario que actualmente está conectado. Parece funcionar bastante bien para mí con FormsAuthentication. Es posible que pueda adaptar este ejemplo a la Autenticación de Windows.


No sé para MVC 2.0, pero en las versiones más recientes puede burlarse del ControllerContext:

// create mock principal var mocks = new MockRepository(MockBehavior.Default); Mock<IPrincipal> mockPrincipal = mocks.Create<IPrincipal>(); mockPrincipal.SetupGet(p => p.Identity.Name).Returns(userName); mockPrincipal.Setup(p => p.IsInRole("User")).Returns(true); // create mock controller context var mockContext = new Mock<ControllerContext>(); mockContext.SetupGet(p => p.HttpContext.User).Returns(mockPrincipal.Object); mockContext.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true); // create controller var controller = new MvcController() { ControllerContext = mock.Object };

ver también ¿Cómo probar la unidad de una acción de controlador MVC que depende de la autenticación en c #?


Para simular WindowsIdentity , puede hacer lo siguiente:

var mockedPrincipal = new Mock<WindowsPrincipal>(WindowsIdentity.GetCurrent()); mockedPrincipal.SetupGet(x => x.Identity.IsAuthenticated).Returns(true); mockedPrincipal.SetupGet(x => x.Identity.Name).Returns("Domain//User1"); mockedPrincipal.Setup(x => x.IsInRole("Domain//Group1")).Returns(true); mockedPrincipal.Setup(x => x.IsInRole("Domain//Group2")).Returns(false);

luego usa mockedPrincipal.Object para obtener la mockedPrincipal.Object actual de WindowsIdentity



Ejemplo de burla de nombre de usuario y SID en MVC4. El nombre de usuario y SID (Autenticación de Windows) en la siguiente acción deben probarse:

[Authorize] public class UserController : Controller { public ActionResult Index() { // get Username ViewBag.Username = User.Identity.Name; // get SID var lIdentity = HttpContext.User.Identity as WindowsIdentity; ViewBag.Sid = lIdentity.User.ToString(); return View(); } }

Yo uso Moq y Visual Studio Test Tools . La prueba se implementa de la siguiente manera:

[TestMethod] public void IndexTest() { // Arrange var myController = new UserController(); var contextMock = new Mock<ControllerContext>(); var httpContextMock = new Mock<HttpContextBase>(); var lWindowsIdentity = new WindowsIdentity("Administrator"); httpContextMock.Setup(x => x.User).Returns(new WindowsPrincipal(lWindowsIdentity)); contextMock.Setup(ctx => ctx.HttpContext).Returns(httpContextMock.Object); myController.ControllerContext = contextMock.Object; // Act var lResult = myController.Index() as ViewResult; // Assert Assert.IsTrue(lResult.ViewBag.Username == "Administrator"); Assert.IsTrue(lResult.ViewBag.Sid == "Any SID Pattern"); }