Unit tests with HttpContext.Current.Session

1,899 views
Skip to first unread message

TheMightyKumquat

unread,
Aug 28, 2009, 2:00:24 AM8/28/09
to Rhino.Mocks
I'm running a lot of unit tests on a class inheriting from another
class, where the base class' methods make a lot of calls involving
HttpContext.Current.Session. When unit tests run, of course, they
fail, because there is no HttpContext when the test is executed by the
Visual Studio IDE.

I've done a bit of Googling for a workaround and found a couple of
things - something called HttpSimulator and also a Scott Hanselman
blog page that discussed trying to simulate Session using Rhino Mocks,
but I don't really understand the usage of either. Does anyone have
experience trying to deal with Session in unit tests, and is there a
"best practice" solution involving Rhino Mocks? I'd love to hear
everyone's input.

Michael Ketting

unread,
Aug 28, 2009, 3:22:57 AM8/28/09
to Rhino.Mocks
Oh yeah, the good old HttpContext :D The solution I've found was to
wrap everything exposed via HttpContext into an wrapper that also
implements an interface that has the same API as the wrapped type.
Thus, I'm free to mock away most of the annoying bits and pieces of
ASP.NET. Using R#, this took me about an hour or so. And so far, it
works quite well for control development.

You can check out an example here:
https://svn.re-motion.org/svn/Remotion/trunk/Remotion/Web/Core/Infrastructure/

Michael

Patrick Steele

unread,
Aug 30, 2009, 12:02:05 PM8/30/09
to rhino...@googlegroups.com
I just went through this yesterday with a MonoRail application that I
needed to add some unit testing to.

The "Home" controller had login and logout methods for logging into
the system. I used ASP.NET Forms Authentication so my login method
had stuff like creating the FormsAuthenticationTicket, creating a
cookie, adding it to the Response.Cookies collection, etc... My
Logout method called FormsAuthentication.SignOut(), Session.Abandon(),
cookie expiration. Also, the HttpApplication had code in the
AuthenticateRequest to determine if the user was already logged on --
again, by digging into cookie values and looking for stuff specific to
FormsAuthentication.

I had to abstract this authentication process into something I could
mock. So I created a simple authentication interface:

public interface IAuthenticationService
{
/// <summary>
/// Signs a user into the system.
/// </summary>
/// <param name="user"></param>
void SignIn(User user);

/// <summary>
/// Signs a user out of the system.
/// </summary>
void SignOut();

/// <summary>
/// Finds the currently logged in user (if any)
/// </summary>
/// <returns>The current user or <c>null</c> if no user was found.</returns>
User FindLoggedInUser();
}

NOTE: The "User" class above is a class in my application that
represents a user.

My Home controller constructor was changed to accept an instance of
IAuthenticationService (which is resolved at run-time by Windsor).
For unit testing, I can create a mock or sub for
IAuthenticationService. For run-time, I created a
FormsAuthenticationService and implemented IAuthenticationService.
This is where all of the old code got moved to (the stuff that dealt
directly with FormsAuthenticationTicket, FormsAuthentication.SignOut,
Session.Abandon, etc...

It worked out really well and I was really happy to get that
FormsAuthentication stuff out of my controller (plus, my login/logout
process now has some automated unit tests!).

--
Patrick Steele
http://weblogs.asp.net/psteele

TheMightyKumquat

unread,
Aug 31, 2009, 4:24:57 AM8/31/09
to Rhino.Mocks
Creating an interface in your code to abstract away the calls to
Session and HttpContext is definitely the way to go. Do that and Rhino
Mocks can solve your issues.

My problem is that I'm testing code that makes calls to
Microsoft.ApplicationBlocks.UIProcess (UIP). It's all the UIP code
that's giving me the problem, and I'm extremely reluctant to rewrite
the code in the App Block. I can't see a way to use Rhino Mocks to
solve this at all.

I found a piece of code called HttpSimulator which is up on Phil
Haack's blog. http://haacked.com/archive/2007/06/19/unit-tests-web-code-without-a-web-server-using-httpsimulator.aspx.

It's great! As far as I've seen so far, you wrap your test code in a
call to the HttpSimulator and it will set up all the HttpContext and
Session fields that would otherwise be missing. It has one problem,
though: HttpContext.Current.Handler still evaluates as null and is
making my tests fail. I have been banging my head against the wall all
day trying to find a workaround for this.

shatl

unread,
Aug 31, 2009, 9:36:39 AM8/31/09
to Rhino.Mocks
You can take a look at implementation of HttpContextLocatorService and
IHttpContext in Web Client Software Factory.
Having interface you could easily mock it with RhinoMocks.

Patrick Steele

unread,
Sep 1, 2009, 11:58:26 AM9/1/09
to rhino...@googlegroups.com
On Mon, Aug 31, 2009 at 4:24 AM, TheMightyKumquat<ree....@gmail.com> wrote:
>
> My problem is that I'm testing code that makes calls to
> Microsoft.ApplicationBlocks.UIProcess (UIP). It's all the UIP code
> that's giving me the problem, and I'm extremely reluctant to rewrite
> the code in the App Block. I can't see a way to use Rhino Mocks to
> solve this at all.

Why not wrap the use of the UIP code in an interface?

Tom Opgenorth

unread,
Sep 1, 2009, 12:25:00 PM9/1/09
to rhino...@googlegroups.com
Phil Haack, about 1.5 ~2 years ago now, released some duck-typing
stuff to put an interface around HttpContext and all those other
sealed classes in ASP.NET. I tried it out a while ago, it seemed to
work not to bad.
--
http://www.opgenorth.net

Tim Barcz

unread,
Sep 1, 2009, 12:33:35 PM9/1/09
to rhino...@googlegroups.com
You referring to the HttpSimulator stuff? If so, +1

but beyond just that stuff "wrap the crap" rely on abstractions and wrap away ugliness/concreteness behind an interface.
--
Tim Barcz
Microsoft ASPInsider
http://timbarcz.devlicio.us
http://www.twitter.com/timbarcz

Tom Opgenorth

unread,
Sep 1, 2009, 1:18:56 PM9/1/09
to rhino...@googlegroups.com
Here's the post, almost two years ago exactly:

http://haacked.com/archive/2007/09/09/ihttpcontext-and-other-interfaces-for-your-duck-typing-benefit.aspx

Probably more of a ASP.NET 2.0 thing these days though.

On Tue, Sep 1, 2009 at 10:33, Tim Barcz<timb...@gmail.com> wrote:
> You referring to the HttpSimulator stuff? If so, +1


--
http://www.opgenorth.net

TheMightyKumquat

unread,
Sep 4, 2009, 7:51:39 AM9/4/09
to Rhino.Mocks
A lot of respondents missed the point of what I was trying to say,
which was that with the tests I'm writing I'm not free to rewrite the
code being tested. If I was, sure, I would be abstracting the ugliness
away into some interfaces that are mockable. But unfortunately I
didn't write the code I'm testing, and the tests I'm writing are an
exercise 'after the fact' to prove that the code is OK and to create a
body of unit tests for it. So I'm stuck with it not having any of its
calls to HttpContext abstracted into mockable interfaces.

Having said that, testing went very smoothly using HttpSimulator. The
structure of the tests I wrote were basically (in VB.Net):

using (new HttpSimulator("/", @"c:\inetpub\").SimulateRequest())

mocks = new MockRepository()

' use Rhino Mocks to mock any objects in the test code that are
possible

mocks.ReplayAll()

' there may be calls to HttpContext in this method, but they'll work
fine because the call's wrapped in the HttpSimulator using statement
testController.RunSomeMethod()

' use assert statements to check the outcome of the code tested
Assert.IsTrue(<stuff that can be verified>)

' Check that everything that had an expectation set up for it in
Rhino Mocks has been called as per the expectation
mocks.VerifyAll()

end using

I had a couple of extra problems - even with the HttpSimulator
working, a couple of things in HttpContext were null. From memory it
was HttpContext.Current.Handler. I had to create a Page object and a
Response object, assign the Response to the Page via Reflection (it's
a readonly property) and assign the Page as the
HttpContext.Current.Handler object to get past that small glitch. But
overall, I'd highly recommend using HttpSimulator if you're stuck not
being able to abstract away calls to HttpContext in the code you're
testing.

Jason Meckley

unread,
Sep 4, 2009, 9:42:11 AM9/4/09
to Rhino.Mocks
I can understand not wanting to rewrite the UIP block to abstract
HttpContext. You could create your own facade for the UIP block though
and make calls against the facade. You would be able to test the UIP
facade because of the dependence on HttpContext, but this is a much
smaller footprint.

if you need to test static/non-virtual try TypeMock.Isolator. I
haven't used it, but it's suppose to work for these scenarios. Roy
Osherove has blogged about this in the past year quite a bit.

shapovalov

unread,
Sep 15, 2009, 8:45:29 AM9/15/09
to Rhino.Mocks
/// <summary>
/// In Unit tests I have no context and have no session
/// so I have to create it manually
/// Now you can get session this way
/// HttpContext.Current.Session
/// </summary>
public void CreateHttpSessionTest()
{
HttpContext.Current = new HttpContext(new HttpRequest
(string.Empty,

"http://localhost/",

string.Empty),
new HttpResponse(new
StringWriter()));

IHttpSessionState iSessState = new
HttpSessionStateContainer(string.Empty,

new SessionStateItemCollection(),

new HttpStaticObjectsCollection(),

20000,

true,

HttpCookieMode.UseCookies,

SessionStateMode.Off,

false);
SessionStateUtility.AddHttpSessionStateToContext(
HttpContext.Current,
iSessState);
Assert.IsNotNull(HttpContext.Current.Session);
Assert.IsNotNull(HttpContext.Current.Cache);
Reply all
Reply to author
Forward
0 new messages