解析ASP.NET MVC项目中视图的单元测试(2)_.Net教程

编辑Tag赚U币
教程Tag:暂无Tag,欢迎添加,赚取U币!

推荐:谈.NET平台编程语言的未来
在去年的PDC2008召开期间,微软逐步公开了围绕.NET和编程语言的很多想法,据此我们可以饶有兴趣地对.NET的未来预测一番。 .NET平台以运行在通用语言运行时(Common Language Runtime,CLR)上的C#和VB.NET作为开端。CLR是通用语言架构(Common Language Infrast

此外,TestViewData还有一些静态方法:

public class TestViewData

{

static TestViewData()

{

PersistentProvider = new InProcPersistentProvider();

}

public static IPersistentProvider PersistentProvider { get; set; }

public static string GenerateHostUrl(TestViewData data)

{

var key = PersistentProvider.Save(data);

return ViewHostHandlerUrl "?key=" HttpUtility.UrlEncode(key);

}

private static string ViewHostHandlerUrl

{

get

{

return ConfigurationManager.AppSettings["UnitView_ViewHostHandlerUrl"]

?? "/UnitView/ViewHostHandler.ashx";

}

}

internal static TestViewData Load(string key)

{

return PersistentProvider.Load(key);

}

...

}

GenerateHostUrl方法将委托PersistentProvider保存对象,并得到一个key。这个key将拼接在ViewHostHandlerUrl属性上,这便是被测试的路径。从代码中可以看出,如果您不想使用默认的测试路径,只需在web.config的AppSettings节点中添加一个目标地址即可。

PersistentProvider属性为IPersistentProvider接口类型,其中定义了Save/Load/Remove三个方法。IPersistentProvider在项目中只有一个实现:InProcPersistentProvider,它会将TestViewData存放在内存中的一个字典里。这个实现已经足够让UnitView结合LTAF运行(LTAF的同进程特性起到了关键的作用)。不过,如果您还是希望使用WatiN等独立进程的测试工具,就必须实现自己的IPersistentProvider类型。例如您可以实现一个FilePersistentProvider,将TestViewData序列化至一个外部文件中,这样就可以在合适的时候将它取回了。

另一个较为关键的类型是UnitView.Engine.ViewHostHandler:

public class ViewHostHandler : IHttpHandler

{

private HttpContext Context { get; set; }

public void ProcessRequest(HttpContext context)

{

this.Context = context;

ControllerContext controllerContext = new ControllerContext(

new HttpContextWrapper(context),

this.Data.RouteData,

new MockController());

new ViewResult

{

MasterName = this.Data.MasterName,

ViewName = this.Data.ViewName,

TempData = this.Data.TempData,

ViewData = this.Data.ViewData,

}.ExecuteResult(controllerContext);

}

private string Key

{

get

{

string key = this.Context.Request.QueryString["key"];

if (String.IsNullOrEmpty(key))

{

throw new ArgumentNullException("key");

}

return key;

}

}

private TestViewData m_data;

private TestViewData Data

{

get

{

if (this.m_data == null)

{

this.m_data = TestViewData.Load(this.Key);

if (this.m_data == null)

{

throw new ArgumentNullException("Cannot retrieve the data.");

}

}

return this.m_data;

}

}

public bool IsReusable { get { return false; } }

}

首先,在ProcessRequest方法会取回TestViewData,并根据这些数据构造一个ViewResult对象,最后执行它的ExecuteResult方法来输出视图内容。由于ExecuteRequest方法的需要,我们还必须构造一个ControllerContext对象,也就意味着我们还必须提供一个Controller对象和HttpContext的封装。从代码中可以看出,我们这里使用了最简单的数据。由于视图遵守“约定”,它只会从ViewData中获取数据,所以无论Controller或HttpContext是什么值都已经无关紧要了。

您可能会想,为什么会有这样的“约定”,不让视图从HttpContext对象中获取数据呢?Mock一个HttpContext对象也不是那么困难(这里要感谢各种强大的Mock框架)啊。可惜,Mock后的HttpContext很难进行序列化,这样就几乎杜绝了跨进程通信的可能,这对于使用WatiN和Selenium进行测试的朋友们无疑是一种灾难。权衡之下,老赵决定放弃对HttpContext的支持。

注1:目前UnitView基于ASP.NET MVC RC构建,当RTM发布后我会进行必要的更新。请关注老赵这篇文章和托管在MSDN Code Gallery上的代码(http://code.msdn.microsoft.com/UnitView)。

注2:在《ASP.NET MVC单元测试最佳实践》中我也包含了UnitView组件,实现略有不同——请以本篇文章为主。

分享:ASP.NET如何防止用户多次登录
常见的处理方法是,在用户登录时,判断此用户是否已经在Application中存在,如果存在就报错,不存在的话就加到Application中(Application是所有Session共有的,整个web应用程序唯一的一个对象): 以下是引用片段: string strUserId = txtUser.Text; ArrayLi

共2页上一页12下一页
来源:模板无忧//所属分类:.Net教程/更新时间:2009-05-16
相关.Net教程