Mock session,cookie,querystring in ASB.NET MVC
写测试用例的时候经常发现,所写的功能需要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-context
- public 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的更多相关文章
- Asp.net MVC使用Model Binding解除Session, Cookie等依赖
上篇文章"Asp.net MVC使用Filter解除Session, Cookie等依赖"介绍了如何使用Filter来解除对于Session, Cookie的依赖.其实这个也可以通 ...
- Asp.net MVC使用Filter解除Session, Cookie等依赖
本文,介绍了Filter在MVC请求的生命周期中的作用和角色,以及Filter的一些常用应用场景. 同时针对MVC中的对于Session,Cookie等的依赖,如何使用Filter解依赖. 如果大家有 ...
- [转]Asp.net MVC使用Filter解除Session, Cookie等依赖
本文转自:http://www.cnblogs.com/JustRun1983/p/3279139.html 本文,介绍了Filter在MVC请求的生命周期中的作用和角色,以及Filter的一些常用应 ...
- web也是区分前端与后端的,session\cookie辨析
<1>Ajax交互方式 Ext.Ajax.request( { //被用来向服务器发起请求默认的url url : "", //请求时发送后台的参数,既可以是Json对 ...
- Asp.net 服务器Application,Session,Cookie,ViewState和Cache区别
2.8 Context 的使用Context 对象包含与当前页面相关的信息,提供对整个上下文的访问,包括请求.响应.以及上文中的Session 和Application 等信息.可以使用此对象在网页之 ...
- session & cookie(li)
Session & Cookie 一.定义 Session,用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览这个网站所花费的时间.Cookie,由服务器端生成,发送 ...
- 浅析session&cookie
session&cookie没有出现的黑暗时代 大家都知道,HTTP协议是一种无状态的协议,本次请求下一次请求没有任何的关联,所有没有办法直接用http协议来记住用户的信息,试想一向,每一次点 ...
- http之Session&Cookie
百度了一波session与Cookie,我发现这东西远比我想象中更复杂(可能是因为我不明白底层的运行原理).网上也是一堆的关于Session与Cookie区别/联系的文章,然而,我看完了还是一脸懵逼的 ...
- [转载]JavaEE学习篇之——Session&&Cookie
原文链接: http://blog.csdn.net/jiangwei0910410003/article/details/23337043 今天继续来看看JavaWeb的相关知识,这篇文章主要来讲一 ...
随机推荐
- WinForm企业级框架实战项目演练
一.课程介绍 我们都知道在软件架构方式分为:C/S和B/S两类.这里阿笨不谈论两种软件架构的优劣之分,因为它们各有千秋,用于不同场合.一位伟大的讲师曾经说过一句话:事物存在即合理!录制这堂课程的目的就 ...
- 【文文殿下】[AH2017/HNOI2017]礼物
题解 二项式展开,然后暴力FFT就好了.会发现有一个卷积与c无关,我们找一个最小的项就行了. Tips:记得要倍长其中一个数组,防止FFT出锅 代码如下: #include<bits/stdc+ ...
- spring mvc 使用kaptcha配置生成验证码实例
SpringMVC整合kaptcha(验证码功能) 一.依赖 <dependency> <groupId>com.github.penggle</groupId> ...
- 【rocketMQ】1、搭建MQ服务器,生产一个订单与消费一个订单
1. 先解压 2. maven编译安装.(注意虚拟机采用nat网络模式,需要联网) mvn -Prelease-all -DskipTests clean install -U 启动nameser节点 ...
- the fist blood of java-eclipse 哈哈哈哈 封装的运用
class Student { private int id; public String name; public String sex; private int score ...
- Java实现二叉树先序,中序,后序,层次遍历
一.以下是我要解析的一个二叉树的模型形状.本文实现了以下方式的遍历: 1.用递归的方法实现了前序.中序.后序的遍历: 2.利用队列的方法实现层次遍历: 3.用堆栈的方法实现前序.中序.后序的遍历. . ...
- 【Canal源码分析】整体架构
本文详解canal的整体架构. 一.整体架构 说明: server代表一个canal运行实例,对应于一个jvm instance对应于一个数据队列 (1个server对应1..n个instance) ...
- ActiveMQ配置高可用性的方式
当一个应用被部署于生产环境,灾备计划是非常重要的,以便从网络故障,硬件故障,软件故障或者电源故障中恢复.通过合理的配置ActiveMQ,可以解决上诉问题.最典型的配置方法是运行多个Broker,一旦某 ...
- 全网最详细的用pip安装****模块报错:Could not find a version that satisfies the requirement ****(from version:) No matching distribution found for ****的解决办法(图文详解)
不多说,直接上干货! 问题详情 这个问题,很普遍.如我这里想实现,Windows下Anaconda2 / Anaconda3里正确下载安装用来向微信好友发送消息的itchat库. 见,我撰写的 全网最 ...
- php -- 表单多选
----- 011-form.html ----- <!DOCTYPE html> <html> <head> <meta http-equiv=" ...