Подтвердить что ты не робот

Единичное тестирование HttpApplication

У меня есть класс, полученный из HttpApplication, который добавляет некоторые дополнительные функции. Я до такой степени, что мне нужно unit test эти функции, а это значит, что я должен иметь возможность создать новый экземпляр HttpApplication, подделать запрос и получить объект ответа.

Как именно я могу выполнить модульное тестирование объекта HttpApplication? Я использую Moq в данный момент, но я понятия не имею, как настроить требуемый макет.

4b9b3361

Ответ 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 и др. часто не ИМХО.

Чтобы установить эту оболочку в mock (используя мой пример 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();

Ответ 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.");
    }