2009-07-25 11 views
12

Mam klasę pochodną od HttpApplication, która dodaje pewne dodatkowe funkcje. Doszedłem do punktu, w którym muszę przetestować te funkcje, co oznacza, że ​​muszę mieć możliwość utworzenia nowej instancji HttpApplication, sfałszowania żądania i pobrania obiektu odpowiedzi.Jednostka testująca HttpApplication

Jak dokładnie testuję obiekt testujący obiekt HttpApplication? Używam w tym momencie Moq, ale nie mam pojęcia, jak skonfigurować wymagany obiekt próbny.

Odpowiedz

10

Niestety, nie jest to szczególnie łatwe, ponieważ aplikacja HttpApplication nie nadaje się do kpiny; nie ma interfejsu, z którego możnaby się udawać, a większość metod nie jest oznaczona jako wirtualna.

Niedawno miałem podobny problem z HttpRequest i HttpWebResponse. W końcu, rozwiązanie poszedłem było stworzenie prostego otoki „pass-through” dla metod chciałem użyć:

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

to niech mnie kpić przeciwko własnym owijki berło. Niekoniecznie najbardziej elegancka rzecz na świecie, ale bardzo przydatny sposób na wyśmiewanie niektórych mniej "mocowanych" części ramy.

Zanim odejdziesz i zrobisz to, warto sprawdzić, co masz, i zobaczyć, czy istnieje lepsze podejście do testów, które pozwoliłyby uniknąć zawijania klas.

W przypadku HttpWebRequest, HttpApplication i innych często nie ma IMHO.

W celu ustalenia tej owijki w udawanym (używając mojego HttpWebRequest przykład powyżej) wtedy robić rzeczy, jak ten z Min:

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

Dzięki za info! Trochę refaktoryzowałem, więc większość dodatkowej funkcjonalności znajduje się teraz w zewnętrznej klasie, która może zostać stworzona tylko z wyśmiewaną HttpContextBase zamiast polegania na HttpApplication. –

2

IMHO dodawanie funkcjonalności poprzez rozszerzenie HttpApplication nie jest najlepszą rzeczą do zrobienia. Trudno wyśmiać HttpContext ze względu na prywatne/wewnętrzne/zamknięte klasy, które nawet jeśli ci się uda, twoje testy jednostkowe będą tak zagracone kpiącym kodem, że nie będziesz w stanie zrozumieć, co faktycznie testujesz.

Czy możesz podać więcej szczegółów na temat funkcji, które dodajesz? Być może istnieje lepszy sposób na dodanie tej funkcjonalności do twojej aplikacji.

2

znalazłem następujące blogu wcześniej, co tłumaczy całkiem miłe podejście za pomocą programu Microsoft Moles .

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

W krótkim roztworze sugeruje następujące:

[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."); 
    } 
Powiązane problemy