对 HttpApplication 进行单元测试

发布于 2024-07-30 01:56:48 字数 186 浏览 5 评论 0原文

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

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

I have a class derived from HttpApplication that adds some extra features. I'm to the point where I need to unit test these features, which means I have to be able to create a new instance of the HttpApplication, fake a request, and retrieve the response object.

How exactly do I go about unit testing an HttpApplication object? I'm using Moq at the moment, but I have no idea how to set up the required mock object.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

秋日私语 2024-08-06 01:56:48

不幸的是,这并不是特别容易做到,因为 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();

Unfortunately, this isn't particularly easy to do, as the HttpApplication doesn't lend itself to mocking very easily; there is no interface to mock against and most of the methods aren't marked as virtual.

I recently had a similar problem with HttpRequest and HttpWebResponse. In the end, the solution I went for was to create a straight "pass-through" wrapper for the methods I wanted to use:

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

This let me mock against my own wrapper interface. Not necessarily the most elegant thing in the world, but a very useful way of mocking out some of the less "mockable" parts of the framework.

Before you rush off and do this though, it is worth reviewing what you've got and seeing if there is a better approach to your tests that would avoid you having to wrap classes.

In the case of HttpWebRequest, HttpApplication et al, there often isn't IMHO.

In order to set this wrapper in mock (using my HttpWebRequest example above) you then do stuff like this with 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();
幽梦紫曦~ 2024-08-06 01:56:48

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

您能否提供有关您要添加的功能的更多详细信息? 也许有更好的方法将此功能添加到您的应用程序中。

IMHO adding a functionality by extending HttpApplication is not the best thing to do. It is so difficult to mock the HttpContext because of the private/internal/sealed classes that even if you succeed your unit tests will be so cluttered with mocking code that you will no longer be able to understand what you are actually testing.

Could you give more details on what functionality you are adding? Maybe there's a better way of adding this functionality to your application.

烙印 2024-08-06 01:56:48

我之前发现了以下博客,其中解释了使用 Microsoft Moles 的相当不错的方法。

http://maraboustork.co.uk/index.html 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.");
    }

I found the following blog earlier which explains quite a nice approach using Microsoft Moles.

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

In short the solution suggests the following:

    [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.");
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文