usar unitarias unit test pruebas mvc mock gavilanch2 ejemplo como asp.net-mvc moq

asp.net mvc - unitarias - Burlarse de HttpContextBase con Moq



pruebas unitarias mvc 5 (2)

Estoy usando una versión de algún código que Steve Sanderson incluyó en su libro Pro Asp.NET MVC ... y actualmente estoy teniendo un dilema moral si está bien publicar el código aquí. ¿Qué tal si me comprometo con una versión muy despojada? ;)

Entonces, esto puede ser reutilizado fácilmente, crea una clase similar a la siguiente a la que pasarás tu controlador. Esto configurará tus simulacros y los configurará en ControllerContext de tu controlador

public class ContextMocks { public Moq.Mock<HttpContextBase> HttpContext { get; set; } public Moq.Mock<HttpRequestBase> Request { get; set; } public RouteData RouteData { get; set; } public ContextMocks(Controller controller) { //define context objects HttpContext = new Moq.Mock<HttpContextBase>(); HttpContext.Setup(x => x.Request).Returns(Request.Object); //you would setup Response, Session, etc similarly with either mocks or fakes //apply context to controller RequestContext rc = new RequestContext(HttpContext.Object, new RouteData()); controller.ControllerContext = new ControllerContext(rc, controller); } }

Y luego, en su método de prueba, simplemente crearía una instancia de ContextMocks y pasaría el objeto del controlador que está probando:

[Test] Public void test() { var mocks = new ContextMocks(controller); var req = controller.Request; //do some asserts on Request object }

Parece muy similar a los ejemplos de Craig, pero esto es con Moq v3. Tengo que darle apoyo a Steve Sanderson para esto; lo estoy usando como base para probar todo tipo de cosas que de otra manera tradicionalmente serían difíciles de probar: cookies, sesión, método de solicitud, querystring ¡y más!

Tengo un accesorio de prueba de unidad en el que estoy tratando de probar un ControllerAction en un controlador ASP.NET MVC que se utiliza para las funciones de membresía en una aplicación web. Estoy intentando burlarme del HttpContext para las pruebas. ControllerAction en prueba realmente establece propiedades en HttpContext, como valores de sesión, valores de Response.Cookies, etc. Esto no es todo el código, pero aquí hay una muestra aproximada de la prueba que estoy tratando de ejecutar :

[Test] public void ValidRegistrationDataSuccessfullyCreatesAndRegistersUser() { var context = new Mock<HttpContextBase>() {DefaultValue = DefaultValue.Mock}; context.SetupAllProperties(); var provider = new Mock<MembershipProvider>(new object[] {context.Object}); var controller = new AccountController(context.Object, provider.Object); // This just sets up a local FormCollection object with valid user data // in it to use to attempt the registration InitializeValidFormData(); ActionResult result = controller.Register(_registrationData); Assert.IsInstanceOfType(typeof(ViewResult), result); // Here is where I''d like to attempt to do Assertions against properties // of the HttpContext, like ensuring that a Session object called "User" // exists, and new auth cookie exists on the Response.Cookies collection. // So far I''ve been unable to successfully check the values of those properties. // I''ve been unsuccessful in getting those properties setup correctly on my // mock object so that my ControllerAction can actually *set* their values, // and that I can make assertions on them afterwards. The above code actually // generates a StackOverflowException (which I''ve reported) on the // context.SetupAllProperties() call. What am I doing wrong, or what do I need // to do to be able to set and assert on those context properties? }

No estoy seguro de lo que estoy haciendo mal, pero me encantaría que alguien me señale la dirección correcta y me muestre cómo configurar este objeto simulado HttpContextBase de modo que mi controlador realmente pueda establecer valores en sus propiedades, y puedo hacer afirmaciones sobre esas propiedades para asegurar que mi ControllerAction está haciendo lo que necesito.

¿Me estoy acercando a esto de la manera incorrecta? Sé que los controladores MVC tienen un ControllerContext que puedo usar para establecer valores para Session, etc., pero no puedo imaginar cómo se podría burlar de algo así sin inyectarlo. ¿Hay alguna forma de hacerlo en su lugar? (También necesito poder pasar el contexto a mi proveedor de membresía) ¿Sería ese un mejor enfoque?

Gracias.


Así es como lo hago .

public static HttpContextBase FakeHttpContext() { var context = new Mock<HttpContextBase>(); var request = new Mock<HttpRequestBase>(); var response = new Mock<HttpResponseBase>(); var session = new Mock<HttpSessionStateBase>(); var server = new Mock<HttpServerUtilityBase>(); var user = new Mock<IPrincipal>(); var identity = new Mock<IIdentity>(); request.Expect(req => req.ApplicationPath).Returns("~/"); request.Expect(req => req.AppRelativeCurrentExecutionFilePath).Returns("~/"); request.Expect(req => req.PathInfo).Returns(string.Empty); response.Expect(res => res.ApplyAppPathModifier(It.IsAny<string>())) .Returns((string virtualPath) => virtualPath); user.Expect(usr => usr.Identity).Returns(identity.Object); identity.ExpectGet(ident => ident.IsAuthenticated).Returns(true); context.Expect(ctx => ctx.Request).Returns(request.Object); context.Expect(ctx => ctx.Response).Returns(response.Object); context.Expect(ctx => ctx.Session).Returns(session.Object); context.Expect(ctx => ctx.Server).Returns(server.Object); context.Expect(ctx => ctx.User).Returns(user.Object); return context.Object; }

Esta es una versión mejorada de la biblioteca MvcMockHelpers lanzada por Scott Hanselman . Este es el código Moq 2.0; la sintaxis es ligeramente diferente en 3.