{"id":233,"date":"2016-03-22T11:00:19","date_gmt":"2016-03-22T09:00:19","guid":{"rendered":"http:\/\/ingeniarius.net\/blog\/?p=233"},"modified":"2016-03-30T11:13:57","modified_gmt":"2016-03-30T09:13:57","slug":"mocking-httpcontext","status":"publish","type":"post","link":"https:\/\/ingeniarius.net\/blog\/2016\/03\/mocking-httpcontext\/","title":{"rendered":"Mocking HttpContext when testing IActionFilters in MVC"},"content":{"rendered":"<p>While trying to figure out how to make a full featured implementation of ContextMock <a href=\"https:\/\/en.wikipedia.org\/wiki\/Builder_pattern\">builder <\/a>based solely on <a href=\"https:\/\/github.com\/moq\">Moq<\/a> in order to make unit tests for an implementation of <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.web.mvc.iactionfilter%28v=vs.118%29.aspx\">IActionFilter<\/a> I stumbled upon a problem :<\/p>\n<blockquote><p>System.NotSupportedException Invalid setup on a non-virtual (overridable in VB) member: x =&gt; x.Values<\/p><\/blockquote>\n<p><!--more--><\/p>\n<p>Then I read some Q&amp;A on <a href=\"http:\/\/stackoverflow.com\/\">stackoverflow<\/a> <a href=\"http:\/\/stackoverflow.com\/questions\/21768767\/invalid-setup-on-a-non-virtual-overridable-in-vb-member\">here<\/a> and <a href=\"http:\/\/stackoverflow.com\/questions\/1962010\/moq-invalid-setup-on-a-non-overridable-member-x-x-getbytitleasdf\">here<\/a> and some others in which in summary is stated that :<\/p>\n<blockquote><p>Moq cannot mock non-virtual methods and sealed classes.<\/p><\/blockquote>\n<p>I really wanted to keep using <a href=\"https:\/\/github.com\/Moq\/moq4\/wiki\/Quickstart\">Mock&lt;T&gt;<\/a> mainly because<\/p>\n<ol>\n<li>it matches nicely with builder pattern which I like to use for unit testing harness.<\/li>\n<li>it has Verify methods which is great for the <a href=\"http:\/\/stackoverflow.com\/a\/1021037\/1042934\">&#8220;assert&#8221;<\/a> section of the unit test.<\/li>\n<\/ol>\n<p>But because I did not manage to get it through I made another implementation based on .NET classes rather then Mock&lt;.Net classes&gt;. The implementation is suitable for extension and serves the needs for &#8220;arranging&#8221; the HttpContext for the unit test of the IActionFilter. So here it is :<\/p>\n<pre class=\"lang:c# decode:true\" title=\"Context Mock Builder\">using System.Collections.Generic;\r\nusing System.IO;\r\nusing System.Reflection;\r\nusing System.Security.Principal;\r\nusing System.Web;\r\nusing System.Web.Mvc;\r\nusing System.Web.Routing;\r\nusing System.Web.SessionState;\r\nusing Moq;\r\n\r\nnamespace Web.Infrastructure.UnitTests\r\n{\r\n    public class ContextMockBuilder\r\n    {\r\n        private readonly HttpRequest _httpRequest;\r\n        private readonly HttpContext _httpContext;\r\n        private readonly HttpContextWrapper _httpContextWrapper;\r\n        private readonly ControllerContext _controllerContext;\r\n        private readonly ActionExecutingContext _actionExecutingContext;\r\n        public Controller OnController { get; private set; }\r\n        public Mock&lt;IPrincipal&gt; User { get; private set; } \r\n        private IPrincipal _user { get; set; }\r\n\r\n        public ContextMockBuilder(Controller controller = null)\r\n        {\r\n            _httpRequest = new HttpRequest(\"\", \"http:\/\/stackoverflow\/\", \"\");\r\n            var stringWriter = new StringWriter();\r\n            var httpResponse = new HttpResponse(stringWriter);\r\n            _httpContext = new HttpContext(_httpRequest, httpResponse);\r\n            _httpContextWrapper = new HttpContextWrapper(_httpContext);\r\n            _controllerContext = new ControllerContext(_httpContextWrapper,new RouteData(), controller ?? new FakeController());\r\n            _actionExecutingContext = new ActionExecutingContext(_controllerContext, new FakeActionDescriptor(), new Dictionary&lt;string, object&gt;());\r\n\r\n            var sessionContainer = new HttpSessionStateContainer(\"id\", new SessionStateItemCollection(),\r\n                                                    new HttpStaticObjectsCollection(), 10, true,\r\n                                                    HttpCookieMode.AutoDetect,\r\n                                                    SessionStateMode.InProc, false);\r\n\r\n            _httpContext.Items[\"AspSession\"] = typeof(HttpSessionState).GetConstructor(\r\n                                        BindingFlags.NonPublic | BindingFlags.Instance,\r\n                                        null,\r\n                                        CallingConventions.Standard,\r\n                                        new[] { typeof(HttpSessionStateContainer) },\r\n                                        null)\r\n                                .Invoke(new object[] { sessionContainer });\r\n        }\r\n\r\n        public HttpContextBase BuildHttpContextBase()\r\n        {\r\n            return this._httpContextWrapper;\r\n        }\r\n\r\n        public ControllerContext BuildControllerContext()\r\n        {\r\n            return this._controllerContext;\r\n        }\r\n\r\n        public ActionExecutingContext BuildActionExecutingContext()\r\n        {\r\n            return this._actionExecutingContext;\r\n        }\r\n\r\n        public ContextMockBuilder WithRouteDataValues(IDictionary&lt;string,string&gt; routeValueDictionary )\r\n        {\r\n            _httpRequest.RequestContext.RouteData.Values.Clear();\r\n            _controllerContext.RouteData.Values.Clear();\r\n\r\n            foreach (var rv in routeValueDictionary)\r\n            {\r\n                _httpRequest.RequestContext.RouteData.Values.Add(rv.Key,rv.Value);\r\n                _controllerContext.RouteData.Values.Add(rv.Key, rv.Value);\r\n            }\r\n\r\n            return this;\r\n        }\r\n\r\n        public ContextMockBuilder WithPrincipal(string username, int userid, string[] roles)\r\n        {\r\n            GenericIdentity identity = new GenericIdentity(username);\r\n            _user = new GenericPrincipal(\r\n                    identity,\r\n                    roles\r\n                    );\r\n\r\n            _httpContext.User = _user;\r\n            return this;\r\n        }\r\n        private class FakeSessionState : HttpSessionStateBase\r\n        {\r\n            Dictionary&lt;string, object&gt; items = new Dictionary&lt;string, object&gt;();\r\n            public override object this[string name]\r\n            {\r\n                get { return items.ContainsKey(name) ? items[name] : null; }\r\n                set { items[name] = value; }\r\n            }\r\n        }\r\n\r\n        private class FakeController : Controller\r\n        {\r\n            \r\n        }\r\n\r\n        private class FakeActionDescriptor : ActionDescriptor \r\n        {\r\n            public override object Execute(ControllerContext controllerContext, IDictionary&lt;string, object&gt; parameters)\r\n            {\r\n                throw new System.NotImplementedException();\r\n            }\r\n\r\n            public override ParameterDescriptor[] GetParameters()\r\n            {\r\n                throw new System.NotImplementedException();\r\n            }\r\n\r\n            public override string ActionName { get; }\r\n            public override ControllerDescriptor ControllerDescriptor { get; }\r\n        }\r\n    }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>While trying to figure out how to make a full featured implementation of ContextMock builder based solely on Moq in order to make unit tests for an implementation of IActionFilter I stumbled upon a problem : System.NotSupportedException Invalid setup on a non-virtual (overridable in VB) member: x =&gt; x.Values<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[23,11],"tags":[24],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/ingeniarius.net\/blog\/wp-json\/wp\/v2\/posts\/233"}],"collection":[{"href":"https:\/\/ingeniarius.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ingeniarius.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ingeniarius.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/ingeniarius.net\/blog\/wp-json\/wp\/v2\/comments?post=233"}],"version-history":[{"count":3,"href":"https:\/\/ingeniarius.net\/blog\/wp-json\/wp\/v2\/posts\/233\/revisions"}],"predecessor-version":[{"id":236,"href":"https:\/\/ingeniarius.net\/blog\/wp-json\/wp\/v2\/posts\/233\/revisions\/236"}],"wp:attachment":[{"href":"https:\/\/ingeniarius.net\/blog\/wp-json\/wp\/v2\/media?parent=233"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ingeniarius.net\/blog\/wp-json\/wp\/v2\/categories?post=233"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ingeniarius.net\/blog\/wp-json\/wp\/v2\/tags?post=233"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}