2009-07-25 11 views
12

Tengo una clase derivada de HttpApplication que agrega algunas características adicionales. Llegué al punto en que necesito probar estas características por unidad, lo que significa que tengo que poder crear una nueva instancia de HttpApplication, falsificar una solicitud y recuperar el objeto de respuesta.Unidad probando una aplicación Http

¿Cómo hago para probar las unidades de un objeto HttpApplication? Estoy usando Moq por el momento, pero no tengo idea de cómo configurar el objeto simulado requerido.

Respuesta

10

Desafortunadamente, esto no es particularmente fácil de hacer, ya que la aplicación Http no se presta para burlarse muy fácilmente; no hay una interfaz para burlarse y la mayoría de los métodos no están marcados como virtuales.

Recientemente tuve un problema similar con HttpRequest y HttpWebResponse. Al final, la solución fui a era crear una envoltura recta de la "transferencia" de los métodos que quería utilizar:

public class HttpWebRequestWrapper : IHttpWebRequestWrapper 
    { 
     private HttpWebRequest httpWebRequest; 

     public HttpWebRequestWrapper(Uri url) 
     { 
      this.httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url); 
     } 

     public Stream GetRequestStream() 
     { 
      return this.httpWebRequest.GetRequestStream(); 
     } 

     public IHttpWebResponseWrapper GetResponse() 
     { 
      return new HttpWebResponseWrapper(this.httpWebRequest.GetResponse()); 
     } 

     public Int64 ContentLength 
     { 
      get { return this.httpWebRequest.ContentLength; } 
      set { this.httpWebRequest.ContentLength = value; } 
     } 

     public string Method 
     { 
      get { return this.httpWebRequest.Method; } 
      set { this.httpWebRequest.Method = value; } 
     } 

     public string ContentType 
     { 
      get { return this.httpWebRequest.ContentType; } 
      set { this.httpWebRequest.ContentType = value; } 
     } 
} 

etc, etc

Esta vamos burlan de mí en contra de mi propio envoltorio interfaz. No necesariamente es la cosa más elegante del mundo, pero es una forma muy útil de burlarse de algunas de las partes menos "ficticias" del marco.

Antes de que se apresure y haga esto, vale la pena revisar lo que tiene y ver si hay un mejor enfoque para sus pruebas que evitaría tener que envolver las clases.

En el caso de HttpWebRequest, HttpApplication et al, a menudo no hay en mi humilde opinión.

Con el fin de establecer este envoltorio con fingida (usando mi HttpWebRequest ejemplo anterior), a continuación, hacer cosas como esta con Moq:

var mockWebRequest = new Mock<IHttpWebRequestWrapper>(); 
mockWebRequest.SetupSet<string>(c => c.Method = "POST").Verifiable(); 
mockWebRequest.SetupSet<string>(c => c.ContentType = "application/x-www-form-urlencoded").Verifiable(); 
mockWebRequest.SetupSet<int>(c => c.ContentLength = 0).Verifiable(); 
+0

Gracias por la info! Refactoreé las cosas un poco, por lo que la mayoría de las funcionalidades adicionales se encuentran ahora en una clase externa que puede crearse solo con una HttpContextBase burlada en lugar de confiar en HttpApplication. –

2

En mi humilde opinión añadir una funcionalidad al extender HttpApplication no es lo mejor que puedes hacer. Es tan difícil burlarse del HttpContext debido a las clases privadas/internas/selladas que, incluso si tienes éxito, tus pruebas unitarias estarán tan llenas de código de burla que ya no podrás entender lo que realmente estás probando.

¿Podría dar más detalles sobre qué funcionalidad está agregando? Tal vez haya una mejor manera de agregar esta funcionalidad a su aplicación.

2

me encontré con el blog siguiente anterior que explica un enfoque bastante bien utilizando Microsoft Moles .

http://maraboustork.co.uk/index.php/2011/03/mocking-httpwebresponse-with-moles/

En pocas palabras la solución sugiere lo siguiente:

[TestMethod] 
    [HostType("Moles")] 
    [Description("Tests that the default scraper returns the correct result")] 
    public void Scrape_KnownUrl_ReturnsExpectedValue() 
    { 
     var mockedWebResponse = new MHttpWebResponse(); 

     MHttpWebRequest.AllInstances.GetResponse = (x) => 
     { 
      return mockedWebResponse; 
     }; 

     mockedWebResponse.StatusCodeGet =() => { return HttpStatusCode.OK; }; 
     mockedWebResponse.ResponseUriGet =() => { return new Uri("http://www.google.co.uk/someRedirect.aspx"); }; 
     mockedWebResponse.ContentTypeGet =() => { return "testHttpResponse"; }; 

     var mockedResponse = "<html> \r\n" + 
          " <head></head> \r\n" + 
          " <body> \r\n" + 
          "  <h1>Hello World</h1> \r\n" + 
          " </body> \r\n" + 
          "</html>"; 

     var s = new MemoryStream(); 
     var sw = new StreamWriter(s); 

      sw.Write(mockedResponse); 
      sw.Flush(); 

      s.Seek(0, SeekOrigin.Begin); 

     mockedWebResponse.GetResponseStream =() => s; 

     var scraper = new DefaultScraper(); 
     var retVal = scraper.Scrape("http://www.google.co.uk"); 

     Assert.AreEqual(mockedResponse, retVal.Content, "Should have returned the test html response"); 
     Assert.AreEqual("http://www.google.co.uk/someRedirect.aspx", retVal.FinalUrl, "The finalUrl does not correctly represent the redirection that took place."); 
    } 
Cuestiones relacionadas