2009-09-02 47 views
21

Las URL de los menús en mis aplicaciones ASP.NET MVC se generan desde el controlador/acciones. Entonces, llaman alASP.NET MVC: Controlador simulado.Url.Action

controller.Url.Action(action, controller) 

Ahora, ¿cómo hago esto para que funcione en pruebas unitarias? utilizo MVCContrib con éxito con

var controller = new TestControllerBuilder().CreateController<OrdersController>(); 

pero lo que trato de hacer con ella consigo controller.Url.Action (acción, controlador) no con NullReferenceException porque Url == null.

Actualización: no se trata de cómo interceptar HttpContext. Hice esto de varias maneras, usando MVCContrib, el ejemplo de falsificación de Scott Hanselman, y también el de http://stephenwalther.com/blog/archive/2008/07/01/asp-net-mvc-tip-12-faking-the-controller-context.aspx. Esto no me ayuda porque necesito saber QUÉ valores falsificar ... ¿es ApplicationPath? ¿Cómo lo configuro? ¿Necesita coincidir con el controlador/acción llamado? Es decir, ¿cómo funciona Url.Action y cómo lo satisfago?

Además, sé que puedo hacer IUrlActionAbstraction e ir con eso ... pero no estoy seguro de querer hacer esto. Después de todo, tengo MVCContrib/Mock full power y ¿por qué necesito otra abstracción?

+0

¿Cuál es su suite de pruebas? –

+1

No vale la pena una respuesta por sí mismo, así que señalaré una respuesta similar: http://bit.ly/aSJ0a –

+0

Sí, utilicé ese enlace y no funcionó. En realidad, probé la versión de Scott y MVCContrib. Lo que trato de entender es qué valores necesito configurar? ¿Qué usa realmente Url.Action()? Es decir. en el enlace que proporcionó hay una versión de Moq que configura MUCHAS variables ... ¿TODAS son necesarias? Intenté todos ellos sin suerte. – queen3

Respuesta

21

Así es como se podría burlarse UrlHelper usando TestControllerBuilder de MvcContrib:

var routes = new RouteCollection(); 
MvcApplication.RegisterRoutes(routes); 
HomeController controller = CreateController<HomeController>(); 

controller.HttpContext.Response 
    .Stub(x => x.ApplyAppPathModifier("/Home/About")) 
    .Return("/Home/About"); 

controller.Url = new UrlHelper(
    new RequestContext(
     controller.HttpContext, new RouteData() 
    ), 
    routes 
); 
var url = controller.Url.Action("About", "Home"); 
Assert.IsFalse(string.IsNullOrEmpty(url)); 
+0

Vaya ... Fue engañoso ver en MSDN help for Controller.Url "Obtiene el objeto auxiliar de URL" ... Ni siquiera verifiqué si tenía setter. – queen3

+0

¿Sabes cómo podríamos lograr esto con MVC4 Darin? Como estoy tratando de seguir el ejemplo del código pero no puedo llamar a RegisterRoutes – DevDave

+2

Tyler: RegisterRoutes es una convención, use MvcApplication.RouteTable.Routes.Add (...) – Shane

3

fingir trabajos sencillos muy bien:

var fakeUrlHelper = A.Fake<UrlHelper>(); 
     controller.Url = fakeUrlHelper; 
     A.CallTo(() => fakeUrlHelper.Action(A<string>.Ignored, A<string>.Ignored)) 
      .Returns("/Action/Controller"); 
+0

+1 bazillion para usar 'FakeItEasy' !! Pero ... el método 'Action' no es virtual ... ¿cómo puedes falsificarlo/interceptarlo? –

3

Si está utilizando Moq (y no MvcContrib 's TestControllerBuilder), se puede burlarse del contexto, similar a la respuesta de @DarianDimitrov:

var controller = new OrdersController(); 
var context = new Mock<System.Web.HttpContextBase>().Object; 

controller.Url = new UrlHelper(
    new RequestContext(context, new RouteData()), 
    new RouteCollection() 
); 

Esto no configura la propiedad controller.HttpContext, pero permite Url.Action ejecutar (y devolver una cadena vacía - no se requiere burla).

13

una forma más limpia de hacer esto es simplemente usar Moq (o cualquier otro marco se quiere) para burlarse de sí UrlHelper

var controller = new OrdersController(); 
var Mock<UrlHelper> UrlHelperMock = new Mock<UrlHelper>(); 

controller.Url = UrlHelperMock.Object; 

UrlHelperMock.Setup(x => x.Action("Action", "Controller", new {parem = "test"})).Returns("testUrl"); 

var url = controller.Url.Action("Action", "Controller", new {parem = "test"}); 
assert.areEqual("/Controller/Action/?parem=test",url); 

limpia y sencilla.

Cuestiones relacionadas