2012-05-08 14 views
5

Estoy escribiendo pruebas de flujo de espectros usando Watin, para una aplicación Asp.Net MVC que usa T4MVC.Usando Asp.Net MVC Rutas de una aplicación no web (pruebas)

Me encuentro utilizando las URL de "cadena mágica" en las pruebas, que no me gustan.

[Given(@"I am on the sign up page")] 
public void GivenIAmOnTheSignUpPage() 
{ 
    string rootUrl = ConfigurationManager.AppSettings["RootUrl"]; 
    string fullUrl = string.Format("{0}/Authentication/Signup",rootUrl); 
    WebBrowser.Current.GoTo(fullUrl); 
} 

que prefiero usar mis resultados de la acción T4MVC como lo hago en la App MVC, algo como esto ...

[Given(@"I am on the sign up page")] 
public void GivenIAmOnTheSignUpPage() 
{ 
    WebBrowser.Current.GoTo(MVC.Authentication.SignUp().ToAbsoluteUrl()); 
} 

mi método ToAbsoluteUrl Extensión

public static class RouteHelper 
{ 
    private static UrlHelper _urlHelper; 
    private static string _rootUrl; 

    public static string ToAbsoluteUrl(this ActionResult result) 
    { 
     EnsureUrlHelperInitialized(); 

     var relativeUrl = _urlHelper.Action(result); 
     return string.Format("{0}/{1}", _rootUrl, relativeUrl); 
    } 

    private static void EnsureUrlHelperInitialized() 
    { 
     if (_urlHelper==null) 
     { 
      _rootUrl = ConfigurationManager.AppSettings["RootUrl"]; 

      var request = new HttpRequest("/", _rootUrl, ""); 
      var response = new HttpResponse(new StringWriter()); 
      var context = new HttpContext(request,response); 
      HttpContext.Current = context; 
      var httpContextBase = new HttpContextWrapper(context); 


      RouteTable.Routes.Clear(); 
      MvcApplication.RegisterRoutes(RouteTable.Routes); 

      var requestContext = new RequestContext(httpContextBase, RouteTable.Routes.GetRouteData(httpContextBase)); 

      _urlHelper = new UrlHelper(requestContext, RouteTable.Routes); 
     } 
    } 
} 

¿Cuál es la forma correcta de inicializar RequestContext y RouteCollection para que pueda generar mis URL de prueba?

Actualmente recibo una NullReferenceException en la línea var requestContext = new RequestContext(httpContextBase, RouteTable.Routes.GetRouteData(httpContextBase));. ¿Es esa la manera correcta de actualizar un requestContext?

O si hay una forma mejor de tomar un ActionResult (de T4MVC) y resolverlo en una url absoluta, fuera de una aplicación web, eso es realmente lo que estoy buscando.

+0

¿Qué unidad de prueba lib está utilizando con SpecFlow? ¿MsTest, NUnit o algo más? – danludwig

+0

Estoy usando xUnit, ¿eso importa? – Brook

+0

No, me preguntaba para poder personalizar mi respuesta. No estoy seguro de cuáles son los equivalentes de xunit para [TestClass] y [AssemblyInitialize], pero imagine que no es difícil de descubrir. – danludwig

Respuesta

5
public static class RouteHelper 
{ 
    private static UrlHelper _urlHelper; 
    private static string _rootUrl; 

    static RouteHelper() 
    { 
     var routes = new RouteCollection(); 
     MvcApplication.RegisterRoutes(routes); 
     var req = new HttpRequest(string.Empty, "http://www.site.com", null); 
     var res = new HttpResponse(null); 
     var ctx = new HttpContext(req, res); // do not use HttpContext.Current 
     var requestContext = new RequestContext(new HttpContextWrapper(ctx), 
      new RouteData()); 
     _urlHelper = new UrlHelper(requestContext, routes); 
     _rootUrl = ConfigurationManager.AppSettings["RootUrl"]; 
    } 

    public static string ToAbsoluteUrl(this ActionResult result) 
    { 
     return string.Format("{0}{1}", _rootUrl, _urlHelper.Action(result)); 
    } 
} 

El constructor estático configura sus campos privados. Elegí usar una nueva RouteCollection, en lugar de usar la propiedad estática RouteTable.Routes, pero es posible que pueda.

No creo que los constructores de HttpRequest y HttpResponse importen. Acabo de pasar algunas cadenas para que construyan sin lanzar una excepción. Úselos para construir un nuevo HttpContext (no use HttpContext.Current cuando se ejecuta desde xUnit). Luego puede ponerlo en un HttpContextWrapper para obtener su referencia HttpContextBase.

Construya un nuevo RequestContext, pasando su contenedor base y una nueva instancia de RouteData. Úselo, junto con su RouteCollection anterior para construir el UrlHelper. Tenga en cuenta que su método de Acción devolverá cadenas precedidas de "/", por lo que debe dejarlo fuera de nuestra aplicación RootUrl (así que use algo como value = "https://develop.site.com" sin la barra al final).

Tenga en cuenta que esto no funcionará para las rutas definidas en áreas MVC. Para eso, necesita registrar las áreas además de llamar RegisterRoutes en asax global.

+0

Eso lo hizo, gracias. Sin embargo, lo cambié para usar el método "Asegurar" en lugar del inicializador de tipo, porque esos tienden a arrojar excepciones muy extrañas cuando ocurren problemas, y dado que esto está leyendo de la configuración, es probable que eso suceda. – Brook

+0

¡Qué salvavidas eres! Busqué en Google esto por horas –

Cuestiones relacionadas