2009-07-25 65 views
12

我有一個派生自HttpApplication的類,它增加了一些額外的功能。我到了需要對這些功能進行單元測試的地步,這意味着我必須能夠創建HttpApplication的新實例,僞造請求並檢索響應對象。單元測試HttpApplication

我到底該如何去測試一個HttpApplication對象的單元測試?目前我正在使用Moq,但我不知道如何設置所需的模擬對象。

回答

10

不幸的是,這並不是特別容易做到,因爲HttpApplication不適合很容易地嘲笑;沒有界面可以嘲笑,大多數方法都沒有標記爲虛擬。

我最近有一個類似的問題,HttpRequest和HttpWebResponse。最後,我去的解決方案是爲方法創建一個直「直通」包裝我想用:

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

等,等

這讓我嘲笑着我自己的包裝接口。不一定是世界上最優雅的東西,而是嘲笑框架中一些不太「可嘲笑」部分的非常有用的方式。

然而,在你急匆匆地做這件事之前,值得回顧一下你所得到的結果,看看你的測試是否有更好的方法來避免你必須包裝課程。

在HttpWebRequest的情況下,HttpApplication等人,經常沒有恕我直言。

爲了設置此包裝在模擬(使用上面我的HttpWebRequest的例子),那麼你做的東西像這樣用起訂量:

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

感謝您的信息!我重構了一些東西,所以現在大多數額外的功能都在外部類中,只能使用模擬的HttpContextBase而不是依賴HttpApplication來創建。 – 2009-07-25 18:13:42

2

恕我直言,通過擴展HttpApplication添加功能不是最好的事情。由於私有/內部/密封類,嘲諷HttpContext是如此困難,即使你成功了,你的單元測試也會因爲模擬代碼而變得混亂,以至於你將不再能夠理解你正在測試的內容。

您能否提供更多關於您要添加的功能的詳細信息?也許有更好的方式將這種功能添加到您的應用程序中。

2

我發現下面的博客早些時候解釋了使用微軟的痣相當不錯的方法。

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

總之解決方案提出以下建議:

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