您的位置:首页 > 理论基础 > 计算机网络

可测试的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将改变,直到我们需要创建一个特别层来实现对它的单元测试。

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: