在C#单元测试中使用HttpContext的简单解决办法
2010-06-13 16:48
411 查看
转载 http://magustest.com/blog/softwaretesting/using-httpcontext-in-unittest/
场景:最近在测试一个.NET的Http Module,这个Module是用来做URL重写的。刚开始进展的比较顺利,因为该Module里面的方法参数基本上都是String,后来这个Module进行了一下重构,所有参数都变成了HttpContext了,这就直接导致原来的单元测试都跑不起来了,接着就开始了弄HttpContext了。
1. 采用Visual Studio自带的ASP.NET单元测试
刚开始我看了一下被测试的代码,虽然说用到了HttpContext,但是有很多地方我都可以绕过去的,意思就是这个HttpContext只是名以上需要的一个参数,只要它不是NULL就可以了,并不影响我的测试,所以我采用了ASP.NET Unit Test的办法来获取一个HttpContext,这个方法实现起来是最简单的,但是会有一些问题,后面会提及到。
首先新建一个WEB项目,然后把被测的Http Module挂到这个新建的WEB项目中。然后就可以配置ASP.NET单元测试,把原来一般的单元测试改造成为一个ASP.NET的单元测试。步骤如下,在测试方法前面加上以下属性
[HostType("ASP.NET")]
[UrlToTest("http://localhost:6988/Default.aspx")]
[AspNetDevelopmentServerHost("D:\\MS_Code\\Public\\UrlRouter.WebTest", "/")]
[UrlToTest] — 这个属性指定了运行该单元测试时的URL
[HostType] — 一般的单元测试是在VSTest的宿主进程下运行,所以是没有HttpContext的;如果作为ASP.NET单元测试,那么必须要在ASP.NET宿主进程下运行
[AspNetDevelopmentServerHost] — 由于我使用了ASP.NET Development Server 作为测试的主机服务器,而不是IIS;所以我需要设置这个属性来指定Web应用程序的完整路径。这里我需要把目录指向刚才新建的WEB项目的路径中。这样子就可以在单元测试中直接使用HttpContext.Current来获取一个HttpContext了。
这样子初步解决了需要HttpContext的困难,但是会有以下问题:
对HttpContext的内容不可控
需要运行ASP.NET Development Server
不能进行调试
2. 直接创建HttpContext实例
基于刚才提到的3个不足,我决定直接创建一个HttpContext来解决问题。还好,HttpContext有公开的构造函数,这个构造函数需要接受一个HttpWorkerRequest作为参数,HttpWorkerRequest是一个抽象类,就是不能直接对之实例化啦,不过好消息是,微软有一个简单的类“SimpleWorkerRequest”,这个类实现了HttpWorkerRequest类;下面是一段简单的代码
这样子就能在单元测试里面用到HttpContext了,好处有:
可以控制HttpContext的内容了,对于URL重写这部分来说,会比较关心请求路径,还有queryString,这两个可以在实例化SimpleWorkerRequest的时候,作为参数传递进去。
不需要ASP.NET Development Server。这个很重要,因为可以满足一个自包含(self-contained)的单元测试的要求
可以调试
3.改良后的方案
到此,世界很美好,测试进行的很顺利。好日子没过多久,我又遇到一个问题,这个URL重写模块,还应用了一个规则引擎,其中进行了大量对HOST判断的操作,很不幸,用刚才的方法创建的HttpContext,它返回的Request.Url中,HOST永远都是127.0.0.1,很郁闷。这时候,一个所有做.NET的人都需要的屠龙刀派上用场了!.NET Reflector,用Reflector打开System.Web.dll,找到System.Web.Hosting这个命名空间,然后找到SimpleWorkerRequest这个类,发现里面的GetLocalAddress()方法,发现里面就是Hard-Code了一个地址:127.0.0.1;好了,知道问题在哪里了,着手写一个新的类,这个类继承SimpleWorkerRequest,然后重写他的GetLocalAddress()方法:
这样子,实例化HttpContext的时候就是这样子:
需要注意的是,对于.appPath和.appVPath的设置是必须的,因为在SimpleWorkerRequest的构造函数中,会取这两个数值。
经过这样的改造,基本上已经满足了测试的需求了。
总结一下:
这个事情居然用了1天多时间,后来发现解决的办法就在我订阅的博客里面就有,以后遇到什么难题先找一个Google Reader。
多用.NET Reflector,Visual Studio经常让你看meta data,那些meta data对我们来说一点用处都没有,还是Reflector好啊。
场景:最近在测试一个.NET的Http Module,这个Module是用来做URL重写的。刚开始进展的比较顺利,因为该Module里面的方法参数基本上都是String,后来这个Module进行了一下重构,所有参数都变成了HttpContext了,这就直接导致原来的单元测试都跑不起来了,接着就开始了弄HttpContext了。
1. 采用Visual Studio自带的ASP.NET单元测试
刚开始我看了一下被测试的代码,虽然说用到了HttpContext,但是有很多地方我都可以绕过去的,意思就是这个HttpContext只是名以上需要的一个参数,只要它不是NULL就可以了,并不影响我的测试,所以我采用了ASP.NET Unit Test的办法来获取一个HttpContext,这个方法实现起来是最简单的,但是会有一些问题,后面会提及到。
首先新建一个WEB项目,然后把被测的Http Module挂到这个新建的WEB项目中。然后就可以配置ASP.NET单元测试,把原来一般的单元测试改造成为一个ASP.NET的单元测试。步骤如下,在测试方法前面加上以下属性
[HostType("ASP.NET")]
[UrlToTest("http://localhost:6988/Default.aspx")]
[AspNetDevelopmentServerHost("D:\\MS_Code\\Public\\UrlRouter.WebTest", "/")]
[UrlToTest] — 这个属性指定了运行该单元测试时的URL
[HostType] — 一般的单元测试是在VSTest的宿主进程下运行,所以是没有HttpContext的;如果作为ASP.NET单元测试,那么必须要在ASP.NET宿主进程下运行
[AspNetDevelopmentServerHost] — 由于我使用了ASP.NET Development Server 作为测试的主机服务器,而不是IIS;所以我需要设置这个属性来指定Web应用程序的完整路径。这里我需要把目录指向刚才新建的WEB项目的路径中。这样子就可以在单元测试中直接使用HttpContext.Current来获取一个HttpContext了。
[[TestMethod] [HostType("ASP.NET")] [AspNetDevelopmentServerHost("D:\\MS_Code\\Public\\UrlRouter.WebTest", "/")] [UrlToTest("http://localhost:6988/Default.aspx")] public void Fuseaction_PUT() { handler = new UrlMapHandler(HttpContext.Current); Assert.IsNotNull(handler); result = handler.ExecuteUrlMap(); StringAssert.Contains(result.Url, "expected string"); }
这样子初步解决了需要HttpContext的困难,但是会有以下问题:
对HttpContext的内容不可控
需要运行ASP.NET Development Server
不能进行调试
2. 直接创建HttpContext实例
基于刚才提到的3个不足,我决定直接创建一个HttpContext来解决问题。还好,HttpContext有公开的构造函数,这个构造函数需要接受一个HttpWorkerRequest作为参数,HttpWorkerRequest是一个抽象类,就是不能直接对之实例化啦,不过好消息是,微软有一个简单的类“SimpleWorkerRequest”,这个类实现了HttpWorkerRequest类;下面是一段简单的代码
TextWriter tw = new StringWriter(); HttpWorkerRequest wr = new SimpleWorkerRequest ("default.aspx", "friendId=1300000000", tw); HttpContext.Current = new HttpContext(wr);
这样子就能在单元测试里面用到HttpContext了,好处有:
可以控制HttpContext的内容了,对于URL重写这部分来说,会比较关心请求路径,还有queryString,这两个可以在实例化SimpleWorkerRequest的时候,作为参数传递进去。
不需要ASP.NET Development Server。这个很重要,因为可以满足一个自包含(self-contained)的单元测试的要求
可以调试
3.改良后的方案
到此,世界很美好,测试进行的很顺利。好日子没过多久,我又遇到一个问题,这个URL重写模块,还应用了一个规则引擎,其中进行了大量对HOST判断的操作,很不幸,用刚才的方法创建的HttpContext,它返回的Request.Url中,HOST永远都是127.0.0.1,很郁闷。这时候,一个所有做.NET的人都需要的屠龙刀派上用场了!.NET Reflector,用Reflector打开System.Web.dll,找到System.Web.Hosting这个命名空间,然后找到SimpleWorkerRequest这个类,发现里面的GetLocalAddress()方法,发现里面就是Hard-Code了一个地址:127.0.0.1;好了,知道问题在哪里了,着手写一个新的类,这个类继承SimpleWorkerRequest,然后重写他的GetLocalAddress()方法:
public class MyWorkerRequest : SimpleWorkerRequest { private string localAdd = string.Empty; public MyWorkerRequest(string page, string query, TextWriter output, string address) : base(page, query, output) { this.localAdd = address; } public override string GetLocalAddress() { return this.localAdd; } }
这样子,实例化HttpContext的时候就是这样子:
Thread.GetDomain().SetData(".appPath", "c:\\inetpub\\wwwroot\\webapp\\"); Thread.GetDomain().SetData(".appVPath", "/"); TextWriter tw = new StringWriter(); String address = "home.myspace.cn"; HttpWorkerRequest wr = new MyWorkerRequest ("default.aspx", "friendId=1300000000", tw, address); HttpContext.Current = new HttpContext(wr);
需要注意的是,对于.appPath和.appVPath的设置是必须的,因为在SimpleWorkerRequest的构造函数中,会取这两个数值。
经过这样的改造,基本上已经满足了测试的需求了。
总结一下:
这个事情居然用了1天多时间,后来发现解决的办法就在我订阅的博客里面就有,以后遇到什么难题先找一个Google Reader。
多用.NET Reflector,Visual Studio经常让你看meta data,那些meta data对我们来说一点用处都没有,还是Reflector好啊。
相关文章推荐
- 在C#单元测试中使用HttpContext的简单解决办法
- 常量,字段,构造方法 调试 ms 源代码 一个C#二维码图片识别的Demo 近期ASP.NET问题汇总及对应的解决办法 c# chart控件柱状图,改变柱子宽度 使用C#创建Windows服务 C#服务端判断客户端socket是否已断开的方法 线程 线程池 Task .NET 单元测试的利剑——模拟框架Moq
- 多线程中使用HttpContext.Current为null的解决办法
- js_html_input中autocomplete="off"在chrom中失效的解决办法 使用JS模拟锚点跳转 js如何获取url参数 C#模拟httpwebrequest请求_向服务器模拟cookie发送 实习期学到的技术(一) LinqPad的变量比较功能 ASP.NET EF 使用LinqPad 快速学习Linq
- 单元测试时候使用[ClassInitialize]会该方法必须是静态的公共方法,不返回值并且应采用一个TestContext类型的参数报错的解决办法
- 多线程中使用HttpContext.Current为null的解决办法
- 使用swiper轮播图手写js之后冲突简单解决办法
- 【已解决】使用android-async-http网络请求框架出现Header[]不识别错误的解决办法
- iOS9 HTTP 不能正常使用的解决办法
- C#强化系列文章八:HttpModule,HttpHandler,HttpHandlerFactory简单使用
- Xcode 7以后在使用HTTP时报错解决办法
- 【解决方法】iOS9 HTTP 不能正常使用的解决办法(数据无法加载)
- iOS9 HTTP 不能正常使用的解决办法
- 集成平台自动登入+C# Login控件,造成的HttpContext.Current.User.Identity.Name 为空问题解决方案
- 简单描述ListView中使用GestureDetector冲突的解决办法
- C#使用读写锁三行代码简单解决多线程并发的问题
- C#使用读写锁三行代码简单解决多线程并发写入文件时线程同步的问题
- http 使用curl发起https请求报错的解决办法
- WCF Service中HttpContext.Current为null的解决办法
- WCF Service中HttpContext.Current为null的解决办法