【问题标题】:Unit testing an HttpApplication对 HttpApplication 进行单元测试
【发布时间】:2009-07-25 15:44:33
【问题描述】:

我有一个派生自 HttpApplication 的类,它添加了一些额外的功能。我已经到了需要对这些功能进行单元测试的地步,这意味着我必须能够创建 HttpApplication 的新实例、伪造请求并检索响应对象。

我该如何对 HttpApplication 对象进行单元测试?我目前正在使用 Moq,但我不知道如何设置所需的模拟对象。

【问题讨论】:

    标签: c# asp.net unit-testing moq httpapplication


    【解决方案1】:

    不幸的是,这并不是特别容易做到的,因为 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 示例),你可以使用 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();
    

    【讨论】:

    • 感谢您的信息!我稍微重构了一下,所以大部分额外的功能现在都在一个外部类中,可以只使用一个模拟的 HttpContextBase 而不是依赖于 HttpApplication 来创建。
    【解决方案2】:

    恕我直言,通过扩展 HttpApplication 添加功能并不是最好的做法。由于私有/内部/密封类,模拟 HttpContext 非常困难,即使您成功了,您的单元测试也会被模拟代码弄得如此混乱,以至于您将不再能够理解您实际测试的内容。

    您能否详细说明您要添加的功能?也许有更好的方法可以将此功能添加到您的应用程序中。

    【讨论】:

      【解决方案3】:

      我之前发现了以下博客,它解释了使用 Microsoft Moles 的一个很好的方法。

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

      【讨论】:

        猜你喜欢
        • 2012-01-08
        • 2012-05-14
        • 2023-03-21
        • 1970-01-01
        • 2019-11-02
        • 1970-01-01
        • 1970-01-01
        • 2010-09-10
        • 2017-12-01
        相关资源
        最近更新 更多