写测试用例的时候经常发现,所写的功能需要Http上下文的支持(session,cookie)这类的.

  以下介绍2种应用场景.

用于控制器内Requet获取参数

  控制器内的Requet其实是控制器内的属性.那么在mock的时候把那些上下文附加到Controller里的控制器上下文(ControllerContext )里,request自然就有东西了.

public Controller(){
/// <summary>
/// 获取或设置控制器上下文。
/// </summary>
///
/// <returns>
/// 控制器上下文。
/// </returns>
public ControllerContext ControllerContext { get; set; }/// <summary>
/// 为当前 HTTP 请求获取 HttpRequestBase 对象。
/// </summary>
///
/// <returns>
/// 请求对象。
/// </returns>
public HttpRequestBase Request
{get{if (this.HttpContext != null)return this.HttpContext.Request;return (HttpRequestBase) null;}
}
}

  

为此,为了单独的Mock这些http上下文中的一些元素,我们需要6个类

Mock类

    //http://stephenwalther.com/archive/2008/07/01/asp-net-mvc-tip-12-faking-the-controller-contextpublic class FakeControllerContext : ControllerContext{//public FakeControllerContext(ControllerBase controller)//    : this(controller, null, null, null, null, null, null)//{//}/// <summary>/// MockCookie/// </summary>/// <param name="controller"></param>/// <param name="cookies"></param>public FakeControllerContext(ControllerBase controller, HttpCookieCollection cookies): this(controller, null, null, null, null, cookies, null){}/// <summary>/// MockSession/// </summary>/// <param name="controller"></param>/// <param name="sessionItems"></param>public FakeControllerContext(ControllerBase controller, SessionStateItemCollection sessionItems): this(controller, null, null, null, null, null, sessionItems){}/// <summary>/// MockForm/// </summary>/// <param name="controller"></param>/// <param name="formParams"></param>public FakeControllerContext(ControllerBase controller, NameValueCollection formParams): this(controller, null, null, formParams, null, null, null){}/// <summary>/// MockForm+QueryString/// </summary>/// <param name="controller"></param>/// <param name="formParams"></param>/// <param name="queryStringParams"></param>public FakeControllerContext(ControllerBase controller, NameValueCollection formParams, NameValueCollection queryStringParams): this(controller, null, null, formParams, queryStringParams, null, null){}public FakeControllerContext(ControllerBase controller, string userName): this(controller, userName, null, null, null, null, null){}public FakeControllerContext(ControllerBase controller, string userName, string[] roles): this(controller, userName, roles, null, null, null, null){}/// <summary>/// Mock Session+Cookie+Form+QuertyString+IIdentity/// </summary>/// <param name="controller">控制器名</param>/// <param name="userName"></param>/// <param name="roles"></param>/// <param name="formParams">Form</param>/// <param name="queryStringParams">QueryString</param>/// <param name="cookies">Cookie</param>/// <param name="sessionItems">Session</param>public FakeControllerContext(ControllerBase controller,string userName,string[] roles,NameValueCollection formParams,NameValueCollection queryStringParams,HttpCookieCollection cookies,SessionStateItemCollection sessionItems): base(new FakeHttpContext(new FakePrincipal(new FakeIdentity(userName), roles),formParams,queryStringParams,cookies, sessionItems), new RouteData(), controller){ }/// <summary>/// /// </summary>/// <param name="controller"></param>/// <param name="formParams"></param>/// <param name="queryStringParams"></param>/// <param name="cookies"></param>/// <param name="sessionItems"></param>/// <param name="userName"></param>/// <param name="roles"></param>public FakeControllerContext(ControllerBase controller,NameValueCollection formParams,NameValueCollection queryStringParams,HttpCookieCollection cookies,SessionStateItemCollection sessionItems,string userName = null,string[] roles = null): base(new FakeHttpContext(new FakePrincipal(new FakeIdentity(userName), roles),formParams,queryStringParams,cookies, sessionItems), new RouteData(), controller){ }}public class FakeHttpContext : HttpContextBase{private readonly FakePrincipal _principal;private readonly NameValueCollection _formParams;private readonly NameValueCollection _queryStringParams;private readonly HttpCookieCollection _cookies;private readonly SessionStateItemCollection _sessionItems;public FakeHttpContext(FakePrincipal principal, NameValueCollection formParams, NameValueCollection queryStringParams, HttpCookieCollection cookies, SessionStateItemCollection sessionItems){_principal = principal;_formParams = formParams;_queryStringParams = queryStringParams;_cookies = cookies;_sessionItems = sessionItems;}public override HttpRequestBase Request { get { return new FakeHttpRequest(_formParams, _queryStringParams, _cookies); } }public override IPrincipal User { get { return _principal; } set { throw new System.NotImplementedException(); } }public override HttpSessionStateBase Session { get { return new FakeHttpSessionState(_sessionItems); } }}public class FakeHttpRequest : HttpRequestBase{private readonly NameValueCollection _formParams;private readonly NameValueCollection _queryStringParams;private readonly HttpCookieCollection _cookies;public FakeHttpRequest(NameValueCollection formParams, NameValueCollection queryStringParams, HttpCookieCollection cookies){_formParams = formParams;_queryStringParams = queryStringParams;_cookies = cookies;}public override NameValueCollection Form{get{return _formParams;}}public override NameValueCollection QueryString{get{return _queryStringParams;}}public override HttpCookieCollection Cookies{get{return _cookies;}}}public class FakeHttpSessionState : HttpSessionStateBase{private readonly SessionStateItemCollection _sessionItems;public FakeHttpSessionState(SessionStateItemCollection sessionItems){_sessionItems = sessionItems;}public override void Add(string name, object value){_sessionItems[name] = value;}public override int Count{get{return _sessionItems.Count;}}public override IEnumerator GetEnumerator(){return _sessionItems.GetEnumerator();}public override NameObjectCollectionBase.KeysCollection Keys{get{return _sessionItems.Keys;}}public override object this[string name]{get{return _sessionItems[name];}set{_sessionItems[name] = value;}}public override object this[int index]{get{return _sessionItems[index];}set{_sessionItems[index] = value;}}public override void Remove(string name){_sessionItems.Remove(name);}}public class FakeIdentity : IIdentity{private readonly string _name;public FakeIdentity(string userName) { _name = userName; }public string AuthenticationType { get { throw new System.NotImplementedException(); } }public bool IsAuthenticated { get { return !String.IsNullOrEmpty(_name); } }public string Name { get { return _name; } }}public class FakePrincipal : IPrincipal{private readonly IIdentity _identity;private readonly string[] _roles;public FakePrincipal(IIdentity identity, string[] roles){_identity = identity;_roles = roles;}public IIdentity Identity { get { return _identity; } }public bool IsInRole(string role){if (_roles == null)return false;return _roles.Contains(role);}}

  在原示例里面那个外国佬还mock了其他东西( IPrincipal User).但对于我来说没这方面需求.

  然后我们测试一下.

测试控制器

  public class TestController : Controller{#region 请求模拟输出public ActionResult TestSession(){return Content(Session["hehe"].ToString());}public ActionResult TestCookie(){var cookie = Request.Cookies["hehe"];if (cookie == null)return new EmptyResult();return Content(cookie.Values["c1"]);}#endregion#region 请求测试public ActionResult TestForm(){string fuckyou = Request.Form["fuckyou"];if (fuckyou == null)return new EmptyResult();return Content(fuckyou);}public ActionResult TestFormAndQueryString(){string form = Request.Form["fuckyou"];string querty = Request.QueryString["fuckyou2"];return Content(form + "," + querty);}public ActionResult TestMuilt(){var session = Session["hehe"].ToString();var cookie = Request.Cookies["hehe"].Values["c1"];string fuckyou = Request.Form["fuckyou"];string querty = Request.QueryString["fuckyou2"];return Content(string.Format("{1} {0} {2} {0}{3} {0} {4} {0}", Environment.NewLine, session, cookie, fuckyou, querty));}#endregion}

  测试类

    [TestClass]public class MockRequestTest{private readonly IUserCenterService _IUserCenterService;public MockRequestTest(){EngineContext.Initialize(false);_IUserCenterService = EngineContext.Current.Resolve<IUserCenterService>();}[Test][TestMethod]public void MockSession(){//_IUserCenterService = EngineContext.Current.Resolve<IUserCenterService>();var controller = new TestController();var sessionItems = new SessionStateItemCollection();sessionItems["hehe"] = 23;controller.ControllerContext = new FakeControllerContext(controller, sessionItems);var result = controller.TestSession() as ContentResult;Assert.AreEqual(result.Content, "23");}[TestMethod]public void MockCookie(){var controller = new TestController();var mockCookie = new HttpCookie("hehe");mockCookie["c1"] = "nima1";mockCookie["c2"] = "nima2";var requestCookie = new HttpCookieCollection() { { mockCookie } };controller.ControllerContext = new FakeControllerContext(controller, requestCookie);var result = controller.TestCookie() as ContentResult;Console.WriteLine(HttpContext.Current == null);Assert.AreEqual("nima1", result.Content);}/// <summary>/// MockForm/// </summary>[TestMethod]public void MockForm(){var controller = new TestController();NameValueCollection form = new FormCollection(){{"fuckyou","1"},{"fuckyou","2"},};controller.ControllerContext = new FakeControllerContext(controller, form);var result = controller.TestForm() as ContentResult;Debug.Assert(false, result.Content);Assert.IsNotNull(result.Content);}/// <summary>/// MockForm/// </summary>[TestMethod]public void MockFormAndQueryString(){var controller = new TestController();NameValueCollection form = new FormCollection(){{"fuckyou","1"},{"fuckyou2","2"},};controller.ControllerContext = new FakeControllerContext(controller, form, form);var result = controller.TestFormAndQueryString() as ContentResult;//Debug.Assert(false, result.Content);Assert.AreEqual("1,2", result.Content);}/// <summary>/// Mock Session+Cookie+Form+QuertyString/// </summary>[TestMethod]public void MockMuilt(){var controller = new TestController();var sessionItems = new SessionStateItemCollection();sessionItems["hehe"] = 23;var mockCookie = new HttpCookie("hehe");mockCookie["c1"] = "nima1";mockCookie["c2"] = "nima2";var requestCookie = new HttpCookieCollection() { { mockCookie } };NameValueCollection form = new FormCollection(){{"fuckyou","1"},{"fuckyou2","2"},};controller.ControllerContext = new FakeControllerContext(controller, form, form, requestCookie, sessionItems);var result = controller.TestMuilt() as ContentResult;Debug.Assert(false,result.Content,string.Format("正确的结果顺序应该是{0};{1};{2};{3};", sessionItems[0], mockCookie["c1"], form["fuckyou"], form["fuckyou2"]));}}

  在上面这个MS测试用例里,我分别测试了

  • Mock session
  • Mock cookie
  • Mock表单
  • Mock 表单+querystring
  • Mock session+cookie+表单+querystring

  都是通过的.

但是这样有个问题.

问题就是:然而这并没有什么卵用.

mock HttpContext.Current

  实际开发的时候.控制器基本打酱油,别的层面需要获取上下文是从HttpContext.Current.Request中获取.如果在刚才的测试用例.控制器输出的是HttpContext.Current.Request.这玩意无疑是null的.因为我们只是把上下文赋值到控制器里的http上下文里面,和HttpContext.Current.Reques是不同的一个概念.

  所以呢,我们需要mock 和HttpContext.Current.Request.

  session的话,比较容易,那就是

SessionStateUtility.AddHttpSessionStateToContext

  cookie的话比较麻烦.HttpRequest.Cookies是一个只读属性,就算用反射赋值也会失败.这里我比较取巧,只用了cookie集合的第一个.有多个的话,可能得把方法改得更恶心一点吧.

代码

  public static class WebExtension{/// <summary>/// 伪造session/// </summary>/// <param name="url"></param>/// <param name="sesion"></param>/// <param name="queryString"></param>/// <param name="requesttype"></param>public static void FakeHttpContext(this string url, SessionStateItemCollection sesion, string queryString = null, string requesttype = null, HttpCookieCollection cookie = null){var stringWriter = new StringWriter();var httpResponce = new HttpResponse(stringWriter);HttpRequest request;if (cookie == null){request = new HttpRequest(string.Empty, url, queryString ?? string.Empty){RequestType = requesttype ?? "GET",};}else{request = new HttpRequest(string.Empty, url, queryString ?? string.Empty){RequestType = requesttype ?? "GET",Cookies = { cookie[0] },};}var httpContext = new HttpContext(request, httpResponce);if (sesion != null){SessionStateUtility.AddHttpSessionStateToContext(httpContext,new HttpSessionStateContainer(SessionNameStorage.Suser,sesion,new HttpStaticObjectsCollection(),20000,true,HttpCookieMode.AutoDetect,SessionStateMode.InProc,false));}if (cookie != null){//无法对只读属性赋值,会导致异常//Type ret = typeof(HttpRequest);//PropertyInfo pr = ret.GetProperty("Cookies");//pr.SetValue(request, cookie, null); //赋值属性}//var sessionContainer = new HttpSessionStateContainer(//    "id",//    new SessionStateItemCollection(),//    new HttpStaticObjectsCollection(),//    10,//    true,//    HttpCookieMode.AutoDetect,//    SessionStateMode.InProc,//    false);//httpContext.Items["AspSession"] =//    typeof(HttpSessionState).GetConstructor(//        BindingFlags.NonPublic | BindingFlags.Instance,//        null,//        CallingConventions.Standard,//        new[] { typeof(HttpSessionStateContainer) },//        null).Invoke(new object[] { sessionContainer });HttpContext.Current = httpContext;}}

  

相应控制器以及测试用例

        public ActionResult TestHttpCurrent(){var a = System.Web.HttpContext.Current;if (a != null){return Content(a.Request.Cookies.Get("hehe").Value);}return Content("");}[TestMethod]public void httpCurrent(){var controller = new TestController();var mockCookie = new HttpCookie("hehe");mockCookie["c1"] = "nima1";mockCookie["c2"] = "nima2";var requestCookie = new HttpCookieCollection() { { mockCookie } };string.Format("{0}/test/TestHttpCurrent", TestHelper.WebRootUrl).FakeHttpContext(sesion: null, cookie: requestCookie);var result = controller.TestHttpCurrent() as ContentResult;Console.WriteLine(result.Content);}

  session就不测了,我平时测试的时候试了无数次都是有的.

备注:

mock cookie那里,如果有更好的实现方式,请告诉我.

标题是故意为之的,代表了我对ASB.NET 的嘲讽.

参考链接:

ASP.NET MVC Tip #12 – Faking the Controller Context

ASP.NET MVC, HttpContext.Current is null while mocking a request

Mock session,cookie,querystring in ASB.NET MVC相关推荐

  1. Asp.net MVC使用Model Binding解除Session, Cookie等依赖

    上篇文章"Asp.net MVC使用Filter解除Session, Cookie等依赖"介绍了如何使用Filter来解除对于Session, Cookie的依赖. 其实这个也可以 ...

  2. Asp.net MVC使用Filter解除Session, Cookie等依赖

    本文,介绍了Filter在MVC请求的生命周期中的作用和角色,以及Filter的一些常用应用场景. 同时针对MVC中的对于Session,Cookie等的依赖,如何使用Filter解依赖. 如果大家有 ...

  3. session,cookie,sessionStorage,localStorage的区别及应用场景

    浏览器的缓存机制提供了可以将用户数据存储在客户端上的方式,可以利用cookie,session等跟服务端进行数据交互. 一.cookie和session cookie和session都是用来跟踪浏览器 ...

  4. 【转】接口测试Session/Cookie笔记(二)

    Windows系统运行计算器命令:calc python显示上一步操作命令:Alt+p python显示上一步操作结果:_(英文下划线) Session是存放在服务器的键值对 ,用于保存客户端的某个特 ...

  5. Application,Session,Cookie,ViewState和Cache区别

    在ASP.NET中,有很多种保存信息的内置对象,如:Application,Session,Cookie,ViewState和Cache等.下面分别介绍它们的用法和区别. 方法 信息量大小 作用域和保 ...

  6. 打印session cookie

    打印session cookie requests.utils.dict_from_cookiejar(session.cookies)

  7. 比较.ASP.NET中Application,Session,Cookie,ViewState和Cache

    在ASP.NET中,有很多种保存信息的内置对象,如:Application,Session,Cookie,ViewState和Cache等.下面分别介绍它们的用法和区别. 方法 信息量大小 作用域和保 ...

  8. session,cookie和token,以及负载均衡

    参考 session,cookie,token 负载均衡的session解决办法 转载于:https://www.cnblogs.com/Jamie1032797633/p/11201972.html

  9. http,session,cookie

    HTTP Session 一.浅析 HTTP协议(http://www.w3.org/Protocols/)是"一次性单向"协议. 服务端不能主动连接客户端,只能被动等待并答复客户 ...

最新文章

  1. react构建淘票票webapp,及react与vue的简单比较。
  2. GPU、FPGA芯片成为增强机器学习能力的“左膀右臂”
  3. java工程打成jar包 - 使用maven assembly插件打包及手动打包
  4. php cpu mac,PHP 获得计算机的唯一标识[CPU,网卡 MAC地址]
  5. php 标点符号,php 过滤英文标点符号及过滤中文标点符号代码
  6. 1443B. Saving the City
  7. 孩子春节猛吃零食怎么办?专家支招:先用蔬菜填饱肚子
  8. win10下安装SQLServer2005
  9. 软件设计模式概念与意义
  10. 从零开始搭建一个K8S的环境
  11. win7升级sp1包
  12. linux ntfs u盘启动盘,u盘NTFS格式制作PE+CDlinux+ubuntu多系统启动盘
  13. 青龙脚本之-饿了么脚本
  14. React---组件通信的方式
  15. uniapp的uniapp navigateTo 点击无法跳转的问题
  16. 加速度,陀螺仪6轴传感器调试心得。
  17. 建模助手 | 关于REVIT的小技巧,你知道多少?
  18. ubuntu下tree命令的使用
  19. TF Live 直播回放丨Frank Wu:当OpenStack遇到Tungsten Fabric
  20. 一月三万用户,我的迅载网盘运营经验

热门文章

  1. 艾伟:FCKeditor 配置、扩展
  2. JS中confirm,alert,prompt函数
  3. 计算机维护系统Win8PE,u启动windows8PE工具箱
  4. 重庆交通大学2019年计算机系收分,重庆交通大学2019年考研复试分数线已公布
  5. 百度地图 点聚合_强强联合聚能网约车场景 首汽约车为百度地图“站台”
  6. 解决k8s中node拉取镜像失败问题
  7. Docker 服务终端 UI 管理工具
  8. java layoutinflater_LayoutInflater(布局服务)
  9. 【MySQL】数据库1 (数据库+基本操作介绍)
  10. 主席树 + 树上倍增 ---- codeforces 587C[树上倍增或者主席树]