{"id":176,"date":"2018-08-16T22:58:49","date_gmt":"2018-08-16T09:58:49","guid":{"rendered":"http:\/\/blog.wiseowls.co.nz\/?p=176"},"modified":"2026-03-08T00:44:40","modified_gmt":"2026-03-07T11:44:40","slug":"another-take-on-abstracting-httpcontext-current","status":"publish","type":"post","link":"https:\/\/blog.wiseowls.co.nz\/index.php\/2018\/08\/16\/another-take-on-abstracting-httpcontext-current\/","title":{"rendered":"Another take on mocking away HttpContext.Current"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\">Static classes and methods are a pain to unit test<\/h3>\n\n\n\n<p>Back in days of WebForms, <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.web.httpcontext(v=vs.110).aspx\" target=\"_blank\" rel=\"noopener noreferrer\">HttpContext<\/a> was the one object to rule them all. It&#8217;s got session state, request and response, cache, errors, server variables and so much more for developers to inspect and play with. HttpContext.Current was by far the easiest way to tap into all of this. But guess what? Static member invocation does not make mocking it out easy.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">MVC controllers are much more unit-test friendly<\/h3>\n\n\n\n<p>Although technically HttpContext hasn&#8217;t gone anywhere with the coming of MVC, it&#8217;s been neatly wrapped into a <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.web.httpcontextwrapper(v=vs.110).aspx\" target=\"_blank\" rel=\"noopener noreferrer\">HttpContextWrapper<\/a> and exposed as controller instance .Context property. Just mock it out and everything will be fine.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">End of story? Well may be<\/h3>\n\n\n\n<p>If you wanted to completely abstract from all HTTP specifics and happen to not need and utility methods that come with it &#8211; you&#8217;re sweet.<br>If, however, for some reason you feel like relying on some utility methods to reduce amount of non-productive mocking, try this trick:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp\">public class MockHttpContext: IDisposable {\n  public HttpContext Current {\n    get;\n    set;\n  }\n  private AppDomain CurrentDomain {\n    get;\n  }\n\n  public MockHttpContext(string url, string query = null, IPrincipal principal = null) {\n    CurrentDomain = Thread.GetDomain();\n    var path = CurrentDomain.BaseDirectory;\n    var virtualDir = \"\/\";\n\n    CurrentDomain.SetData(\".appDomain\", \"*\");\n    CurrentDomain.SetData(\".appPath\", path);\n    CurrentDomain.SetData(\".appId\", \"testId\");\n    CurrentDomain.SetData(\".appVPath\", virtualDir);\n    CurrentDomain.SetData(\".hostingVirtualPath\", virtualDir);\n    CurrentDomain.SetData(\".hostingInstallDir\", HttpRuntime.AspInstallDirectory);\n    CurrentDomain.SetData(\".domainId\", CurrentDomain.Id);\n\n    \/\/ User is logged out by default\n    principal = principal ?? new GenericPrincipal(\n      new GenericIdentity(string.Empty),\n      new string[0]\n    );\n\n    Current = new HttpContext(\n      new HttpRequest(\"\", url, query),\n      new HttpResponse(new StringWriter())\n    ) {\n      User = principal\n    };\n    HttpContext.Current = Current;\n  }\n\n  public void Dispose() {\n    \/\/clean up\n    HttpContext.Current = null;\n  }\n}<\/code><\/pre>\n\n\n\n<p>First it looks very similar to <a rel=\"noopener noreferrer\" href=\"https:\/\/stackoverflow.com\/questions\/4379450\/mock-httpcontext-current-in-test-init-method\" target=\"_blank\">this implementation taken from SO<\/a> (well, this is where it&#8217;s been taken off to begin with). But then what&#8217;s up with all these <code>CurrentDomain.SetData<\/code> calls? This allows us to mock paths and transition between relative and absolute urls as if we were hosted somewhere.<br>Consider the code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp\">public static string ToAbsoluteUrl(this string relativeUrl) {\n  if (string.IsNullOrEmpty(relativeUrl)) return relativeUrl;\n  if (HttpContext.Current == null) return relativeUrl;\n\n  if (relativeUrl.StartsWith(\"\/\")) relativeUrl = relativeUrl.Insert(0, \"~\");\n  if (!relativeUrl.StartsWith(\"~\/\")) relativeUrl = relativeUrl.Insert(0, \"~\/\");\n\n  var url = HttpContext.Current.Request.Url;\n  var port = !url.IsDefaultPort ? \":\" + url.Port : string.Empty;\n\n  return $ \"{url.Scheme}:\/\/{url.Host}{port}{VirtualPathUtility.ToAbsolute(relativeUrl)}\"; \/\/ and this is where the magic happens. Now static invocation of VirtualPathUtility does not fail with NullReferenceException anymore!\n}<\/code><\/pre>\n\n\n\n<p>The code outside makes afew assumptions regarding the environment being mocked, but it should be a trivial task to introduce more parameters\/settings and mock everything away.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Static classes and methods are a pain to unit test Back in days of WebForms, HttpContext was the one object to rule them all. It&#8217;s got session state, request and response, cache, errors, server variables and so much more for developers to inspect and play with. HttpContext.Current was by far the easiest way to tap &hellip; <a href=\"https:\/\/blog.wiseowls.co.nz\/index.php\/2018\/08\/16\/another-take-on-abstracting-httpcontext-current\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Another take on mocking away HttpContext.Current&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[11],"tags":[12,13,10],"class_list":["post-176","post","type-post","status-publish","format-standard","hentry","category-dev","tag-c","tag-httpcontext","tag-mstest"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Another take on mocking away HttpContext.Current - Timur and associates<\/title>\n<meta name=\"description\" content=\"Integration testing ASP.NET applications is tricky. To help with that, we&#039;ll attempt to abstract from HttpContext - one of the key objects in the pipeline.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.wiseowls.co.nz\/index.php\/2018\/08\/16\/another-take-on-abstracting-httpcontext-current\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Another take on mocking away HttpContext.Current - Timur and associates\" \/>\n<meta property=\"og:description\" content=\"Integration testing ASP.NET applications is tricky. To help with that, we&#039;ll attempt to abstract from HttpContext - one of the key objects in the pipeline.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.wiseowls.co.nz\/index.php\/2018\/08\/16\/another-take-on-abstracting-httpcontext-current\/\" \/>\n<meta property=\"og:site_name\" content=\"Timur and associates\" \/>\n<meta property=\"article:published_time\" content=\"2018-08-16T09:58:49+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-03-07T11:44:40+00:00\" \/>\n<meta name=\"author\" content=\"timur\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@TimurKh\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2018\\\/08\\\/16\\\/another-take-on-abstracting-httpcontext-current\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2018\\\/08\\\/16\\\/another-take-on-abstracting-httpcontext-current\\\/\"},\"author\":{\"name\":\"timur\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/#\\\/schema\\\/person\\\/34d0ed30d573b5bc317ea990bd2e0c59\"},\"headline\":\"Another take on mocking away HttpContext.Current\",\"datePublished\":\"2018-08-16T09:58:49+00:00\",\"dateModified\":\"2026-03-07T11:44:40+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2018\\\/08\\\/16\\\/another-take-on-abstracting-httpcontext-current\\\/\"},\"wordCount\":253,\"keywords\":[\"c#\",\"httpcontext\",\"mstest\"],\"articleSection\":[\"Development\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2018\\\/08\\\/16\\\/another-take-on-abstracting-httpcontext-current\\\/\",\"url\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2018\\\/08\\\/16\\\/another-take-on-abstracting-httpcontext-current\\\/\",\"name\":\"Another take on mocking away HttpContext.Current - Timur and associates\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/#website\"},\"datePublished\":\"2018-08-16T09:58:49+00:00\",\"dateModified\":\"2026-03-07T11:44:40+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/#\\\/schema\\\/person\\\/34d0ed30d573b5bc317ea990bd2e0c59\"},\"description\":\"Integration testing ASP.NET applications is tricky. To help with that, we'll attempt to abstract from HttpContext - one of the key objects in the pipeline.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2018\\\/08\\\/16\\\/another-take-on-abstracting-httpcontext-current\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2018\\\/08\\\/16\\\/another-take-on-abstracting-httpcontext-current\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2018\\\/08\\\/16\\\/another-take-on-abstracting-httpcontext-current\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Another take on mocking away HttpContext.Current\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/#website\",\"url\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/\",\"name\":\"Timur and associates\",\"description\":\"Notes of an IT contractor\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/#\\\/schema\\\/person\\\/34d0ed30d573b5bc317ea990bd2e0c59\",\"name\":\"timur\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg\",\"caption\":\"timur\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/TimurKh\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Another take on mocking away HttpContext.Current - Timur and associates","description":"Integration testing ASP.NET applications is tricky. To help with that, we'll attempt to abstract from HttpContext - one of the key objects in the pipeline.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.wiseowls.co.nz\/index.php\/2018\/08\/16\/another-take-on-abstracting-httpcontext-current\/","og_locale":"en_US","og_type":"article","og_title":"Another take on mocking away HttpContext.Current - Timur and associates","og_description":"Integration testing ASP.NET applications is tricky. To help with that, we'll attempt to abstract from HttpContext - one of the key objects in the pipeline.","og_url":"https:\/\/blog.wiseowls.co.nz\/index.php\/2018\/08\/16\/another-take-on-abstracting-httpcontext-current\/","og_site_name":"Timur and associates","article_published_time":"2018-08-16T09:58:49+00:00","article_modified_time":"2026-03-07T11:44:40+00:00","author":"timur","twitter_card":"summary_large_image","twitter_creator":"@TimurKh","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2018\/08\/16\/another-take-on-abstracting-httpcontext-current\/#article","isPartOf":{"@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2018\/08\/16\/another-take-on-abstracting-httpcontext-current\/"},"author":{"name":"timur","@id":"https:\/\/blog.wiseowls.co.nz\/#\/schema\/person\/34d0ed30d573b5bc317ea990bd2e0c59"},"headline":"Another take on mocking away HttpContext.Current","datePublished":"2018-08-16T09:58:49+00:00","dateModified":"2026-03-07T11:44:40+00:00","mainEntityOfPage":{"@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2018\/08\/16\/another-take-on-abstracting-httpcontext-current\/"},"wordCount":253,"keywords":["c#","httpcontext","mstest"],"articleSection":["Development"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2018\/08\/16\/another-take-on-abstracting-httpcontext-current\/","url":"https:\/\/blog.wiseowls.co.nz\/index.php\/2018\/08\/16\/another-take-on-abstracting-httpcontext-current\/","name":"Another take on mocking away HttpContext.Current - Timur and associates","isPartOf":{"@id":"https:\/\/blog.wiseowls.co.nz\/#website"},"datePublished":"2018-08-16T09:58:49+00:00","dateModified":"2026-03-07T11:44:40+00:00","author":{"@id":"https:\/\/blog.wiseowls.co.nz\/#\/schema\/person\/34d0ed30d573b5bc317ea990bd2e0c59"},"description":"Integration testing ASP.NET applications is tricky. To help with that, we'll attempt to abstract from HttpContext - one of the key objects in the pipeline.","breadcrumb":{"@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2018\/08\/16\/another-take-on-abstracting-httpcontext-current\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.wiseowls.co.nz\/index.php\/2018\/08\/16\/another-take-on-abstracting-httpcontext-current\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2018\/08\/16\/another-take-on-abstracting-httpcontext-current\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.wiseowls.co.nz\/"},{"@type":"ListItem","position":2,"name":"Another take on mocking away HttpContext.Current"}]},{"@type":"WebSite","@id":"https:\/\/blog.wiseowls.co.nz\/#website","url":"https:\/\/blog.wiseowls.co.nz\/","name":"Timur and associates","description":"Notes of an IT contractor","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.wiseowls.co.nz\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blog.wiseowls.co.nz\/#\/schema\/person\/34d0ed30d573b5bc317ea990bd2e0c59","name":"timur","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg","url":"https:\/\/secure.gravatar.com\/avatar\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg","caption":"timur"},"sameAs":["https:\/\/x.com\/TimurKh"]}]}},"_links":{"self":[{"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/posts\/176","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/comments?post=176"}],"version-history":[{"count":10,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/posts\/176\/revisions"}],"predecessor-version":[{"id":937,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/posts\/176\/revisions\/937"}],"wp:attachment":[{"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/media?parent=176"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/categories?post=176"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/tags?post=176"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}