2009-07-25 12 views
12

Ho una classe derivata da HttpApplication che aggiunge alcune funzionalità extra. Sono al punto in cui ho bisogno di testare queste caratteristiche unitarie, il che significa che devo essere in grado di creare una nuova istanza di HttpApplication, fingere una richiesta e recuperare l'oggetto risposta.Unit test a HttpApplication

Come faccio esattamente a testare un oggetto HttpApplication? Al momento sto usando Moq, ma non ho idea di come impostare l'oggetto fittizio richiesto.

risposta

10

Sfortunatamente, questo non è particolarmente facile da fare, in quanto la HttpApplication non si presta a sbeffeggiare molto facilmente; non esiste un'interfaccia per deridere e la maggior parte dei metodi non sono contrassegnati come virtuali.

Recentemente ho avuto un problema simile con HttpRequest e HttpWebResponse. Alla fine, la soluzione sono andato per era quello di creare un involucro dritta "pass-through" per i metodi che ho voluto usare:

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; } 
     } 
} 

ecc, ecc

Questo mi prendo gioco contro il mio involucro interfaccia. Non è necessariamente la cosa più elegante del mondo, ma è un modo molto utile di prendere in giro alcune delle parti meno "schernibili" del framework.

Prima di precipitarsi e fare questo però, vale la pena rivedere quello che hai e vedere se c'è un approccio migliore per i test che eviterebbe di dover avvolgere classi.

Nel caso di HttpWebRequest, HttpApplication et al, spesso non c'è IMHO.

Per impostare questo involucro in finto (usando il mio HttpWebRequest esempio di cui sopra) si poi fare cose come questa 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

Grazie per le informazioni! Ho rifattorato un po 'le cose, quindi la maggior parte delle funzionalità extra ora si trova in una classe esterna che può essere creata con un HttpContextBase solo per il gioco delle mire invece di fare affidamento sull'HttpApplication. –

2

IMHO aggiungendo una funzionalità estendendo HttpApplication non è la cosa migliore da fare. È così difficile prendere in giro l'HttpContext a causa delle classi private/interne/sigillate che anche se si riescono i test dell'unità saranno così ingombri di codice di simulazione che non sarà più possibile capire cosa si sta effettivamente testando.

Potrebbe fornire maggiori dettagli su quale funzionalità si sta aggiungendo? Forse c'è un modo migliore per aggiungere questa funzionalità alla tua applicazione.

2

ho trovato il seguente blog precedente che spiega un approccio molto carino utilizzando Microsoft Moles .

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

Insomma la soluzione suggerisce la seguente:

[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."); 
    }