zoukankan      html  css  js  c++  java
  • 可测试的HttpModule和HttpHandler

    用新的System.Web.Abstraction名称空间我们能轻易写出可测试的HttpModule和HttpHandler。在这篇post中,
    我将向你展示如何写可测试的HttpModule和HttpHandler。

    之前发布的System.Web.Abstraction的单元测试这些web的基础构件HttpContext的问题。它是密封的,无法用Rhino或Moq来mock.唯一的选择是为这些不能MOCK的对象创建包装对象,但它又有像HttpRequest, HttpResponse, HttpSessionState, HttpServerUtility等。同时这的确是System.Web.Abstraction所提供的,所有包在外面不可mock的HttpContext对象。但是HttpModule 和HttpHandler紧密依赖于原生HttpContext之上,我希望ASP.NET 4.0将改变,直到我们需要创建一个特别层来实现对它的单元测试。

    HttpModule

    1. public abstract class BaseHttpModule : IHttpModule   
    2. {   
    3.     public void Init(HttpApplication context)   
    4.     {   
    5.         context.BeginRequest += (sender, e) => OnBeginRequest(new HttpContextWrapper(((HttpApplication) sender).Context));   
    6.         context.Error += (sender, e) => OnError(new HttpContextWrapper(((HttpApplication) sender).Context));   
    7.         context.EndRequest += (sender, e) => OnEndRequest(new HttpContextWrapper(((HttpApplication) sender).Context));   
    8.     }   
    9.   
    10.     public void Dispose()   
    11.     {   
    12.     }   
    13.   
    14.     public virtual void OnBeginRequest(HttpContextBase context)   
    15.     {   
    16.     }   
    17.   
    18.     public virtual void OnError(HttpContextBase context)   
    19.     {   
    20.     }   
    21.   
    22.     public virtual void OnEndRequest(HttpContextBase context)   
    23.     {   
    24.     }   
    25. }  

    如果你的应用程序需要,它能挂起其它事件。现在让我们创建一个基本的从url访问的HttpModule:

    1. public class RemoveWwwModule : BaseHttpModule   
    2. {   
    3.     public override void OnBeginRequest(HttpContextBase context)   
    4.     {   
    5.         const string Prefix = "http://www.";   
    6.   
    7.         string url = context.Request.Url.ToString();   
    8.   
    9.         bool startsWith3W = url.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase);   
    10.   
    11.         if (startsWith3W)   
    12.         {   
    13.             string newUrl = "http://" + url.Substring(Prefix.Length);   
    14.   
    15.             HttpResponseBase response = context.Response;   
    16.   
    17.             response.StatusCode = (int) HttpStatusCode.MovedPermanently;   
    18.             response.Status = "301 Moved Permanently";   
    19.             response.RedirectLocation = newUrl;   
    20.             response.SuppressContent = true;   
    21.             response.End();   
    22.         }   
    23.     }   
    24. }  

    Unit Test:

    1. public class RemoveWwwModuleFixture   
    2. {   
    3.     private readonly Mock<HttpContextBase> _httpContext;   
    4.     private readonly Mock<HttpRequestBase> _httpRequest;   
    5.     private readonly Mock<HttpResponseBase> _httpResponse;   
    6.   
    7.     public RemoveWwwModuleFixture()   
    8.     {   
    9.         _httpContext = new Mock<HttpContextBase>();   
    10.         _httpRequest = new Mock<HttpRequestBase>();   
    11.         _httpResponse = new Mock<HttpResponseBase>();   
    12.   
    13.         _httpContext.SetupGet(context => context.Request).Returns(_httpRequest.Object);   
    14.         _httpContext.SetupGet(context => context.Response).Returns(_httpResponse.Object);   
    15.     }   
    16.   
    17.     [Fact]   
    18.     public void OnBeginRequest_Should_Redirect_When_Requesting_Url_Which_Starts_With_WWW()   
    19.     {   
    20.         _httpRequest.SetupGet(request => request.Url).Returns(new Uri("http://www.mysite.com/"));   
    21.   
    22.         _httpResponse.SetupSet(response => response.StatusCode = (int) HttpStatusCode.MovedPermanently);   
    23.         _httpResponse.SetupSet(response => response.Status = "301 Moved Permanently");   
    24.         _httpResponse.SetupSet(response => response.RedirectLocation = "http://mysite.com/");   
    25.         _httpResponse.SetupSet(response => response.SuppressContent = true);   
    26.         _httpResponse.Setup(response => response.End());   
    27.   
    28.         var module = new RemoveWwwModule();   
    29.   
    30.         module.OnBeginRequest(_httpContext.Object);   
    31.   
    32.         _httpResponse.VerifyAll();   
    33.     }   
    34. }  

    HttpHandler

    1. public abstract class BaseHttpHandler : IHttpHandler   
    2. {   
    3.     public virtual bool IsReusable   
    4.     {   
    5.         get  
    6.         {   
    7.             return false;   
    8.         }   
    9.     }   
    10.   
    11.     public void ProcessRequest(HttpContext context)   
    12.     {   
    13.         ProcessRequest(new HttpContextWrapper(context));   
    14.     }   
    15.   
    16.     public abstract void ProcessRequest(HttpContextBase context);   
    17. }  

    现在让我们创建结合些Javascript文件的HttpHandler,我将在Post中跳过如果是不相关的部分。

    1. public class JavaScriptHandler : BaseHttpHandler   
    2. {   
    3.     public override void ProcessRequest(HttpContextBase context)   
    4.     {   
    5.         string content = GetContent();   
    6.         HttpResponseBase response = context.Response;   
    7.   
    8.         response.ContentType = "application/x-javascript";   
    9.         response.Write(content);   
    10.     }   
    11.   
    12.     private string GetContent()   
    13.     {   
    14.         return "YOUR JAVA SCRIPT FILES CONTENT";   
    15.     }   
    16. }  

    Unit Test:

    1. public class JavaScriptHandlerFixture : IDisposable   
    2. {   
    3.     private readonly Mock<HttpContextBase> _httpContext;   
    4.     private readonly Mock<HttpResponseBase> _httpResponse;   
    5.   
    6.     private readonly JavaScriptHandler _handler;   
    7.   
    8.     public JavaScriptHandlerFixture()   
    9.     {   
    10.         _httpContext = new Mock<HttpContextBase>();   
    11.         _httpResponse = new Mock<HttpResponseBase>();   
    12.   
    13.         _httpContext.SetupGet(context => context.Response).Returns(_httpResponse.Object);   
    14.   
    15.         _handler = new JavaScriptHandler();   
    16.     }   
    17.   
    18.     public void Dispose()   
    19.     {   
    20.         _httpResponse.VerifyAll();   
    21.     }   
    22.   
    23.     [Fact]   
    24.     public void ProcessRequest_Should_Set_Correct_ContentType()   
    25.     {   
    26.         _httpResponse.SetupSet(response => response.ContentType = "application/x-javascript");   
    27.   
    28.         _handler.ProcessRequest(_httpContext.Object);   
    29.     }   
    30.   
    31.     [Fact]   
    32.     public void ProcessRequest_Should_Write_Content()   
    33.     {   
    34.         _httpResponse.Setup(response => response.Write(It.IsAny<string>()));   
    35.   
    36.         _handler.ProcessRequest(_httpContext.Object);   
    37.     }   
    38. }  

    如果你要看更多的可单元测试HttpModule and HttpHandler,到KiGG源代中查看吧。

    翻译:Petter Liu   http://wintersun.cnblogs.com   原文:Source

  • 相关阅读:
    GIL
    CRM2Stark组件
    Django图书管理系统(单表操作)
    Python(ATM机low版)
    Python(9-18天总结)
    Python(1-8天总结)
    Python习题(分页显示)
    Python文本操作2
    Python递归二分法
    Python文本操作
  • 原文地址:https://www.cnblogs.com/wintersun/p/1412057.html
Copyright © 2011-2022 走看看