可测试的HttpModule和HttpHandler
2009-03-14 21:33
204 查看
.posthead {
margin: 0;
padding: 1em 0 0.5em;
text-align: right;
font-size: 0.9em;
}
.posthead h2
{
color: #0000CC;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 1.1em;
}
.posthead h2 {
font-size: 1.1em;
margin: 0;
padding: 0.5em 0;
letter-spacing: 1px;
text-transform: uppercase;
text-align: left;
}
.dp-highlighter
{
font-family: "Consolas", "Courier New", Courier, mono, serif;
font-size: 12px;
background-color: #E7E5DC;
width: 99%;
overflow: auto;
margin: 18px 0 18px 0 !important;
padding-top: 1px; /* adds a little border on top when controls are hidden */
}
.dp-highlighter .bar
{
padding-left: 45px;
}
.dp-highlighter .tools
{
padding: 3px 8px 3px 10px;
font: 9px Verdana, Geneva, Arial, Helvetica, sans-serif;
color: silver;
background-color: #f8f8f8;
padding-bottom: 10px;
border-left: 3px solid #6CE26C;
}
.dp-highlighter .tools a
{
font-size: 9px;
color: #a0a0a0;
background-color: inherit;
text-decoration: none;
margin-right: 10px;
}
.dp-highlighter a,
.dp-highlighter a:hover
{
background: none;
border: none;
padding: 0;
margin: 0;
}
.dp-highlighter ol
{
list-style: decimal; /* for ie */
background-color: #fff;
margin: 0px 0px 1px 45px !important; /* 1px bottom margin seems to fix occasional Firefox scrolling */
padding: 0px;
color: #5C5C5C;
}
.dp-highlighter ol,
.dp-highlighter ol li,
.dp-highlighter ol li span
{
margin: 0;
padding: 0;
border: none;
}
.dp-highlighter ol li.alt
{
background-color: #FFF;
color: inherit;
}
.dp-highlighter ol li,
.dp-highlighter .columns div
{
list-style: decimal-leading-zero; /* better look for others, override cascade from OL */
list-style-position: outside !important;
border-left: 3px solid #6CE26C;
background-color: #F8F8F8;
color: #5C5C5C;
padding: 0 3px 0 10px !important;
margin: 0 !important;
line-height: 14px;
}
.dp-highlighter ol li span
{
color: black;
background-color: inherit;
}
.dp-highlighter .keyword { color: #069; font-weight: bold; background-color: inherit; }
.dp-highlighter .string { color: blue; background-color: inherit; }
用新的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将改变,直到我们需要创建一个特别层来实现对它的单元测试。
{
public void Init(HttpApplication context)
{
context.BeginRequest += (sender, e) => OnBeginRequest(new HttpContextWrapper(((HttpApplication) sender).Context));
context.Error += (sender, e) => OnError(new HttpContextWrapper(((HttpApplication) sender).Context));
context.EndRequest += (sender, e) => OnEndRequest(new HttpContextWrapper(((HttpApplication) sender).Context));
}
public void Dispose()
{
}
public virtual void OnBeginRequest(HttpContextBase context)
{
}
public virtual void OnError(HttpContextBase context)
{
}
public virtual void OnEndRequest(HttpContextBase context)
{
}
}
如果你的应用程序需要,它能挂起其它事件。现在让我们创建一个基本的从url访问的HttpModule:
public class RemoveWwwModule : BaseHttpModule
{
public override void OnBeginRequest(HttpContextBase context)
{
const string Prefix = "http://www.";
string url = context.Request.Url.ToString();
bool startsWith3W = url.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase);
if (startsWith3W)
{
string newUrl = "http://" + url.Substring(Prefix.Length);
HttpResponseBase response = context.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
response.Status = "301 Moved Permanently";
response.RedirectLocation = newUrl;
response.SuppressContent = true;
response.End();
}
}
}
Unit Test:
public class RemoveWwwModuleFixture
{
private readonly Mock<HttpContextBase> _httpContext;
private readonly Mock<HttpRequestBase> _httpRequest;
private readonly Mock<HttpResponseBase> _httpResponse;
public RemoveWwwModuleFixture()
{
_httpContext = new Mock<HttpContextBase>();
_httpRequest = new Mock<HttpRequestBase>();
_httpResponse = new Mock<HttpResponseBase>();
_httpContext.SetupGet(context => context.Request).Returns(_httpRequest.Object);
_httpContext.SetupGet(context => context.Response).Returns(_httpResponse.Object);
}
[Fact]
public void OnBeginRequest_Should_Redirect_When_Requesting_Url_Which_Starts_With_WWW()
{
_httpRequest.SetupGet(request => request.Url).Returns(new Uri("http://www.mysite.com/"));
_httpResponse.SetupSet(response => response.StatusCode = (int) HttpStatusCode.MovedPermanently);
_httpResponse.SetupSet(response => response.Status = "301 Moved Permanently");
_httpResponse.SetupSet(response => response.RedirectLocation = "http://mysite.com/");
_httpResponse.SetupSet(response => response.SuppressContent = true);
_httpResponse.Setup(response => response.End());
var module = new RemoveWwwModule();
module.OnBeginRequest(_httpContext.Object);
_httpResponse.VerifyAll();
}
}
{
public virtual bool IsReusable
{
get
{
return false;
}
}
public void ProcessRequest(HttpContext context)
{
ProcessRequest(new HttpContextWrapper(context));
}
public abstract void ProcessRequest(HttpContextBase context);
}
现在让我们创建结合些Javascript文件的HttpHandler,我将在Post中跳过如果是不相关的部分。
public class JavaScriptHandler : BaseHttpHandler
{
public override void ProcessRequest(HttpContextBase context)
{
string content = GetContent();
HttpResponseBase response = context.Response;
response.ContentType = "application/x-javascript";
response.Write(content);
}
private string GetContent()
{
return "YOUR JAVA SCRIPT FILES CONTENT";
}
}
Unit Test:
public class JavaScriptHandlerFixture : IDisposable
{
private readonly Mock<HttpContextBase> _httpContext;
private readonly Mock<HttpResponseBase> _httpResponse;
private readonly JavaScriptHandler _handler;
public JavaScriptHandlerFixture()
{
_httpContext = new Mock<HttpContextBase>();
_httpResponse = new Mock<HttpResponseBase>();
_httpContext.SetupGet(context => context.Response).Returns(_httpResponse.Object);
_handler = new JavaScriptHandler();
}
public void Dispose()
{
_httpResponse.VerifyAll();
}
[Fact]
public void ProcessRequest_Should_Set_Correct_ContentType()
{
_httpResponse.SetupSet(response => response.ContentType = "application/x-javascript");
_handler.ProcessRequest(_httpContext.Object);
}
[Fact]
public void ProcessRequest_Should_Write_Content()
{
_httpResponse.Setup(response => response.Write(It.IsAny<string>()));
_handler.ProcessRequest(_httpContext.Object);
}
}
如果你要看更多的可单元测试HttpModule and HttpHandler,到KiGG源代中查看吧。
翻译:Petter Liu http://wintersun.cnblogs.com 原文:Source
margin: 0;
padding: 1em 0 0.5em;
text-align: right;
font-size: 0.9em;
}
.posthead h2
{
color: #0000CC;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 1.1em;
}
.posthead h2 {
font-size: 1.1em;
margin: 0;
padding: 0.5em 0;
letter-spacing: 1px;
text-transform: uppercase;
text-align: left;
}
.dp-highlighter
{
font-family: "Consolas", "Courier New", Courier, mono, serif;
font-size: 12px;
background-color: #E7E5DC;
width: 99%;
overflow: auto;
margin: 18px 0 18px 0 !important;
padding-top: 1px; /* adds a little border on top when controls are hidden */
}
.dp-highlighter .bar
{
padding-left: 45px;
}
.dp-highlighter .tools
{
padding: 3px 8px 3px 10px;
font: 9px Verdana, Geneva, Arial, Helvetica, sans-serif;
color: silver;
background-color: #f8f8f8;
padding-bottom: 10px;
border-left: 3px solid #6CE26C;
}
.dp-highlighter .tools a
{
font-size: 9px;
color: #a0a0a0;
background-color: inherit;
text-decoration: none;
margin-right: 10px;
}
.dp-highlighter a,
.dp-highlighter a:hover
{
background: none;
border: none;
padding: 0;
margin: 0;
}
.dp-highlighter ol
{
list-style: decimal; /* for ie */
background-color: #fff;
margin: 0px 0px 1px 45px !important; /* 1px bottom margin seems to fix occasional Firefox scrolling */
padding: 0px;
color: #5C5C5C;
}
.dp-highlighter ol,
.dp-highlighter ol li,
.dp-highlighter ol li span
{
margin: 0;
padding: 0;
border: none;
}
.dp-highlighter ol li.alt
{
background-color: #FFF;
color: inherit;
}
.dp-highlighter ol li,
.dp-highlighter .columns div
{
list-style: decimal-leading-zero; /* better look for others, override cascade from OL */
list-style-position: outside !important;
border-left: 3px solid #6CE26C;
background-color: #F8F8F8;
color: #5C5C5C;
padding: 0 3px 0 10px !important;
margin: 0 !important;
line-height: 14px;
}
.dp-highlighter ol li span
{
color: black;
background-color: inherit;
}
.dp-highlighter .keyword { color: #069; font-weight: bold; background-color: inherit; }
.dp-highlighter .string { color: blue; background-color: inherit; }
用新的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
public abstract class BaseHttpModule : IHttpModule{
public void Init(HttpApplication context)
{
context.BeginRequest += (sender, e) => OnBeginRequest(new HttpContextWrapper(((HttpApplication) sender).Context));
context.Error += (sender, e) => OnError(new HttpContextWrapper(((HttpApplication) sender).Context));
context.EndRequest += (sender, e) => OnEndRequest(new HttpContextWrapper(((HttpApplication) sender).Context));
}
public void Dispose()
{
}
public virtual void OnBeginRequest(HttpContextBase context)
{
}
public virtual void OnError(HttpContextBase context)
{
}
public virtual void OnEndRequest(HttpContextBase context)
{
}
}
public abstract class BaseHttpModule : IHttpModule { public void Init(HttpApplication context) { context.BeginRequest += (sender, e) => OnBeginRequest(new HttpContextWrapper(((HttpApplication) sender).Context)); context.Error += (sender, e) => OnError(new HttpContextWrapper(((HttpApplication) sender).Context)); context.EndRequest += (sender, e) => OnEndRequest(new HttpContextWrapper(((HttpApplication) sender).Context)); } public void Dispose() { } public virtual void OnBeginRequest(HttpContextBase context) { } public virtual void OnError(HttpContextBase context) { } public virtual void OnEndRequest(HttpContextBase context) { } }}
如果你的应用程序需要,它能挂起其它事件。现在让我们创建一个基本的从url访问的HttpModule:
public class RemoveWwwModule : BaseHttpModule
{
public override void OnBeginRequest(HttpContextBase context)
{
const string Prefix = "http://www.";
string url = context.Request.Url.ToString();
bool startsWith3W = url.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase);
if (startsWith3W)
{
string newUrl = "http://" + url.Substring(Prefix.Length);
HttpResponseBase response = context.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
response.Status = "301 Moved Permanently";
response.RedirectLocation = newUrl;
response.SuppressContent = true;
response.End();
}
}
}
public class RemoveWwwModule : BaseHttpModule { public override void OnBeginRequest(HttpContextBase context) { const string Prefix = "http://www."; string url = context.Request.Url.ToString(); bool startsWith3W = url.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase); if (startsWith3W) { string newUrl = "http://" + url.Substring(Prefix.Length); HttpResponseBase response = context.Response; response.StatusCode = (int) HttpStatusCode.MovedPermanently; response.Status = "301 Moved Permanently"; response.RedirectLocation = newUrl; response.SuppressContent = true; response.End(); } } }
Unit Test:
public class RemoveWwwModuleFixture
{
private readonly Mock<HttpContextBase> _httpContext;
private readonly Mock<HttpRequestBase> _httpRequest;
private readonly Mock<HttpResponseBase> _httpResponse;
public RemoveWwwModuleFixture()
{
_httpContext = new Mock<HttpContextBase>();
_httpRequest = new Mock<HttpRequestBase>();
_httpResponse = new Mock<HttpResponseBase>();
_httpContext.SetupGet(context => context.Request).Returns(_httpRequest.Object);
_httpContext.SetupGet(context => context.Response).Returns(_httpResponse.Object);
}
[Fact]
public void OnBeginRequest_Should_Redirect_When_Requesting_Url_Which_Starts_With_WWW()
{
_httpRequest.SetupGet(request => request.Url).Returns(new Uri("http://www.mysite.com/"));
_httpResponse.SetupSet(response => response.StatusCode = (int) HttpStatusCode.MovedPermanently);
_httpResponse.SetupSet(response => response.Status = "301 Moved Permanently");
_httpResponse.SetupSet(response => response.RedirectLocation = "http://mysite.com/");
_httpResponse.SetupSet(response => response.SuppressContent = true);
_httpResponse.Setup(response => response.End());
var module = new RemoveWwwModule();
module.OnBeginRequest(_httpContext.Object);
_httpResponse.VerifyAll();
}
}
public class RemoveWwwModuleFixture { private readonly Mock<HttpContextBase> _httpContext; private readonly Mock<HttpRequestBase> _httpRequest; private readonly Mock<HttpResponseBase> _httpResponse; public RemoveWwwModuleFixture() { _httpContext = new Mock<HttpContextBase>(); _httpRequest = new Mock<HttpRequestBase>(); _httpResponse = new Mock<HttpResponseBase>(); _httpContext.SetupGet(context => context.Request).Returns(_httpRequest.Object); _httpContext.SetupGet(context => context.Response).Returns(_httpResponse.Object); } [Fact] public void OnBeginRequest_Should_Redirect_When_Requesting_Url_Which_Starts_With_WWW() { _httpRequest.SetupGet(request => request.Url).Returns(new Uri("http://www.mysite.com/")); _httpResponse.SetupSet(response => response.StatusCode = (int) HttpStatusCode.MovedPermanently); _httpResponse.SetupSet(response => response.Status = "301 Moved Permanently"); _httpResponse.SetupSet(response => response.RedirectLocation = "http://mysite.com/"); _httpResponse.SetupSet(response => response.SuppressContent = true); _httpResponse.Setup(response => response.End()); var module = new RemoveWwwModule(); module.OnBeginRequest(_httpContext.Object); _httpResponse.VerifyAll(); } }}
HttpHandler
public abstract class BaseHttpHandler : IHttpHandler{
public virtual bool IsReusable
{
get
{
return false;
}
}
public void ProcessRequest(HttpContext context)
{
ProcessRequest(new HttpContextWrapper(context));
}
public abstract void ProcessRequest(HttpContextBase context);
}
现在让我们创建结合些Javascript文件的HttpHandler,我将在Post中跳过如果是不相关的部分。
public class JavaScriptHandler : BaseHttpHandler
{
public override void ProcessRequest(HttpContextBase context)
{
string content = GetContent();
HttpResponseBase response = context.Response;
response.ContentType = "application/x-javascript";
response.Write(content);
}
private string GetContent()
{
return "YOUR JAVA SCRIPT FILES CONTENT";
}
}
public class JavaScriptHandler : BaseHttpHandler { public override void ProcessRequest(HttpContextBase context) { string content = GetContent(); HttpResponseBase response = context.Response; response.ContentType = "application/x-javascript"; response.Write(content); } private string GetContent() { return "YOUR JAVA SCRIPT FILES CONTENT"; } }
Unit Test:
public class JavaScriptHandlerFixture : IDisposable
{
private readonly Mock<HttpContextBase> _httpContext;
private readonly Mock<HttpResponseBase> _httpResponse;
private readonly JavaScriptHandler _handler;
public JavaScriptHandlerFixture()
{
_httpContext = new Mock<HttpContextBase>();
_httpResponse = new Mock<HttpResponseBase>();
_httpContext.SetupGet(context => context.Response).Returns(_httpResponse.Object);
_handler = new JavaScriptHandler();
}
public void Dispose()
{
_httpResponse.VerifyAll();
}
[Fact]
public void ProcessRequest_Should_Set_Correct_ContentType()
{
_httpResponse.SetupSet(response => response.ContentType = "application/x-javascript");
_handler.ProcessRequest(_httpContext.Object);
}
[Fact]
public void ProcessRequest_Should_Write_Content()
{
_httpResponse.Setup(response => response.Write(It.IsAny<string>()));
_handler.ProcessRequest(_httpContext.Object);
}
}
public class JavaScriptHandlerFixture : IDisposable { private readonly Mock<HttpContextBase> _httpContext; private readonly Mock<HttpResponseBase> _httpResponse; private readonly JavaScriptHandler _handler; public JavaScriptHandlerFixture() { _httpContext = new Mock<HttpContextBase>(); _httpResponse = new Mock<HttpResponseBase>(); _httpContext.SetupGet(context => context.Response).Returns(_httpResponse.Object); _handler = new JavaScriptHandler(); } public void Dispose() { _httpResponse.VerifyAll(); } [Fact] public void ProcessRequest_Should_Set_Correct_ContentType() { _httpResponse.SetupSet(response => response.ContentType = "application/x-javascript"); _handler.ProcessRequest(_httpContext.Object); } [Fact] public void ProcessRequest_Should_Write_Content() { _httpResponse.Setup(response => response.Write(It.IsAny<string>())); _handler.ProcessRequest(_httpContext.Object); } }}
如果你要看更多的可单元测试HttpModule and HttpHandler,到KiGG源代中查看吧。
翻译:Petter Liu http://wintersun.cnblogs.com 原文:Source
相关文章推荐
- HttpHandler与HttpModule的用处与区别
- 关于HttpModule和HttpHandler
- HttpModule和Http Handler (比较与区别)
- HttpModule和HttpHandler的常见用法
- ASP.NET的(HttpModule,HttpHandler)
- HttpModule与HttpHandler详解
- HttpModule与HttpHandler详解(转)
- 关于HttpModule和HttpHandler
- HttpModule与HttpHandler详解(转)
- HttpModule,HttpHandler,HttpHandlerFactory简单使用
- HttpHandler和HttpModule--入门
- HttpHandler与HttpModule的理解与应用
- HttpModule与HttpHandler详解(转载)
- HttpModule,HttpHandler,HttpHandlerFactory
- 选择HttpHandler还是HttpModule?(转)
- ASP.NET的必须知道的东东(HttpModule,HttpHandler)之一
- [转]HttpModule与HttpHandler详解
- 选择HttpHandler还是HttpModule?
- ASP.NET的必须知道的东东(HttpModule,HttpHandler)
- 由一道面试题引发的 HttpModule,HttpHandler与IHttpAsyncHandler 详解