About a month and a half ago Ben Scheirman wrote about testing TempData in ASP.NET MVC. It’s good stuff, and aside from changes between Preview 1 and Preview 2, it still works fine. (See Scott Hanselman’s post for some Preview 2-friendly mock helpers using Rhino Mocks.)
While I can easily understand what Ben’s code is doing, what I couldn’t figure out is why it worked. If you reflect over TempDataDictionary (the type of the Controller.TempData property), you’ll see that the data type it persists to the session is an internal structure.

Ben’s code, however, mocks out the Session to return the expected TempDataDictionary object. By all counts, that should fail, since the TempDataDictionary won’t be getting back the values it expects–it expects the internal map structure.
Well, it turns out I was glossing over one very important fact. TempDataDictionary was written to be smart enough that if the underlying session store either didn’t work, or didn’t provide the right data, TempData will continue to operate as normal–for the current request only. You can see below that if the session data was null or wasn’t the right type, it just creates a new internal map.

(image cut off for space)
One of the benefits of TempData is the cross-request persistence via the session. You might not have known it, but when you call RedirectToAction in your controller action, for example, it’s actually resulting in a 300-level HTTP redirect, which means an entirely new HttpContext for the next request. It’s basically deferring to the browser to perform the redirect.
So, while Ben’s code will definitely work, here’s an extension method that can help with mocking out the session a little more “correctly”:
public static void NullifySessionState(this HttpSessionStateBase session) { SetupResult.For(session[null]).IgnoreArguments().Return(null); session[null] = null; LastCall.IgnoreArguments(); }


Leave a comment