Mock HttpContext and Session State
One of the most useful things I came across when doing the asp.net project that i wrote about in my last 2 posts was this article and sample solution by Jason Bock on mocking the HttpContext session state in .net 1.1 and 2.0. Actually this is not a ‘mock’ interface in the sense of mock objects but a real HttpContext which is artificially built by calling into some API’s and which can be used in non web scenarios. I’ll explain why I needed this and how I used it below.
I had to make use of caching in the solution and started of using the HttpRuntime Cache which can also be used from non web applications and is very useful when driving your app through NUnit. Of course, with my new found love of interfaces and mock objects i wrote up an ICacheHandler interface and implemented a WebCacheHandler that wraps the System.Web.Cache. I did consider using EntLib but i dont really need any offline caching etc. System.Web is more than enough. This cache is a dependency for the Service Agent so i stuck my DI hat on and injected it into the service agent through the constructor.
Now heres a gotcha. If you simply use the System.Web.Cache object and try to call the Add() method, then when there is no web context (say when you are unit testing), the Cache will be null and you will get an “object reference not set to instance of an object” errors. So you need to use HttpRuntime.Cache.Add() .
We then decided that for certain situations the application level caching could actually prove counterproductive and what we really needed was Session level caching. There isnt much data to store anyway so theres no chance of knocking down the server with all the session level caching. Since I had my nice lCacheHandler, i wrote up another SessionCacheHandler to use session state. This is where the wheels fell off for a couple of hours. Session state is not like the HttpRuntime Cache. It cannot exist without a valid HttpContext (which is rather obvious and sensible and all that but not helpful in that situation) so the system which was working with the WebCacheHandler when called through NUnit now simply barfed at all calls to add data to the cache.
I knew i had to fool the system into thinking there was a valid HttpContext so i could test the code properly offline without needing to launch the web application so after trawling through the web i found the article by Jason Bock (linked above). The way i used this tool was to set a dependency on HttpContext in my SessionCacheHandler and allow a HttpContext to be injected via property injection. A CacheHandlerFactory class then does the job of setting up the session handler and injecting either this MockHttpContext or the real HttpContext.Current and returning the sessionCacheHandler for use by any caller. This works fine now and i can peacefully run the tests without needing a full web context.
Thinking about EntLib again, i guess a more EntLib oriented approach would be to make this custom component into a sort of ‘SessionCache’ provider for the Caching Application Block and let entlib read a config setting. That way it can also be used through PIAB. Gotta start looking into that option now at least for self education.
It should be interesting to see whats coming up in ASP.NET 3.5 . Apparently there are lots of interfaces for these static things like HttpContext etc which will allow them to be mocked or substituted at runtime/testing so maybe this kind of thing will get easier as time goes on. Meanwhile, i’ve got a nice addition to my toolset. I’m beginning to really like dependency injection. Now for the next step – DI Containers!!
[UPDATE- 18 Feb 2009]: Just to point out that there are limitations in Jason’s utility. It is good for session usage but I ran into problems when I wanted the HttpContext to have stuff like Physical Application Path and things like Headers in the context which cant be done through Jasons code. So the tool that i then turned to was Phil Haack’s HttpSimulator. This was incredibly useful when developing MockingBird.