I've seen how to Fake the SessionState object in MVC using Scott Hanselmans MvcMockHelpers, but I'm dealing with a separate problem.
What I like to do is create a wrapper around the Session object to make objects a little more accessible and strongly typed rather than using keys all over. Here is basically what it does:
So that I can just do this in my controllers and views:
SessionVars s =newSessionVars(); s.CheckoutEmail="test@tester.com";
Now the problem comes in when I want to write unit tests, this class is tightly coupled with the HttpSessionState. What I can't figure out is what is the right class to accept/pass so that I can pass in a FakeHttpSession into the SessionVars class. I've tried
so many things with this, and this (below) will compile, but it can't cast the HttpSessionState into the IDictionary. I've tried ICollection, HttpSessionStateBase.
I'm missing something big here. I feel like this is possible and that I should even be that far off.
Furthermore, I'm confused as to whether I should use the IHttpSessionState, HttpSessionStateBase or the HttpSessionStateWrapper. What is the abstract type that I'd use for the session object inside my SessionVars class? What is the type that I pass into the
constructor?
dependency injection"ASP.NET MVC"unit testing ASP.NET
In unit tests you should instantiate your session variables class like this:
var myVarsCollection = new Dictionary<string,object>();
myVarsCollection.Add("UserId", 1);
myVarsCollection.Add("UserName", "ThisIsMe");
...
var sessionVars = new SessionVars(myVarsCollection);
myVarsCollection is your custom collection with faked session values. In your app code you use parameterless constructor. In tests you use constructor that takes dictionary with values you give. Just like code example I gave. This way you can avoid using all
these session state classes in your tests.
Don't forget to mark solution providing post as "Answered".
Thanks for your response, but I think you may have misunderstood my question. The code I pasted builds, but doesn't run because it cannot cast the SessionState to an IDicitionary<string, object>.
But I think I've solved my own problem and I'll post the code here shortly.
So I figured it out, what my problem was that I had tried so many types for the constructor and abstract class, but I didn't take enough time to figure out why the one I thought should work didn't work.
Currently, HttpSessionState does not derive from HttpSessionStateBase. So you cannot simply cast from HttpSessionState to HttpSessionStateBase. So to handle this, Microsoft had introduced the HttpSessionStateWrapper to allow casting this way. BUT, you cannot
cast the other way since the session may not always be available.
Here is what I ended up figuring out:
public SessionVars() : this( new HttpSessionStateWrapper(HttpContext.Current.Session) )
{ }
public SessionVars(HttpSessionStateBase sessionWrapper)
{
Session = sessionWrapper;
}
public HttpSessionStateBase Session
{
get;
private set;
}
I can use the new HttpSessionStateWrapper(HttpContext.Current.Session) to cast the current session to the HttpSessionStateBase, which can be used to serve up fake sessions and real ones.
mase
Member
54 Points
65 Posts
Injecting the session into a wrapper class
Aug 13, 2010 05:39 PM|LINK
I've seen how to Fake the SessionState object in MVC using Scott Hanselmans MvcMockHelpers, but I'm dealing with a separate problem.
What I like to do is create a wrapper around the Session object to make objects a little more accessible and strongly typed rather than using keys all over. Here is basically what it does:
So that I can just do this in my controllers and views:
Now the problem comes in when I want to write unit tests, this class is tightly coupled with the HttpSessionState. What I can't figure out is what is the right class to accept/pass so that I can pass in a FakeHttpSession into the SessionVars class. I've tried so many things with this, and this (below) will compile, but it can't cast the HttpSessionState into the IDictionary. I've tried ICollection, HttpSessionStateBase.
I'm missing something big here. I feel like this is possible and that I should even be that far off.
Furthermore, I'm confused as to whether I should use the IHttpSessionState, HttpSessionStateBase or the HttpSessionStateWrapper. What is the abstract type that I'd use for the session object inside my SessionVars class? What is the type that I pass into the constructor?
dependency injection "ASP.NET MVC" unit testing ASP.NET
DigiMortal
Contributor
5728 Points
954 Posts
MVP
Re: Injecting the session into a wrapper class
Aug 13, 2010 07:22 PM|LINK
In unit tests you should instantiate your session variables class like this:
var myVarsCollection = new Dictionary<string,object>(); myVarsCollection.Add("UserId", 1); myVarsCollection.Add("UserName", "ThisIsMe"); ... var sessionVars = new SessionVars(myVarsCollection);myVarsCollection is your custom collection with faked session values. In your app code you use parameterless constructor. In tests you use constructor that takes dictionary with values you give. Just like code example I gave. This way you can avoid using all these session state classes in your tests.
Also visit my ASP.NET blog or follow me @ Twitter:twitter.com/gpeipman
mase
Member
54 Points
65 Posts
Re: Injecting the session into a wrapper class
Aug 13, 2010 09:04 PM|LINK
Thanks for your response, but I think you may have misunderstood my question. The code I pasted builds, but doesn't run because it cannot cast the SessionState to an IDicitionary<string, object>.
But I think I've solved my own problem and I'll post the code here shortly.
mase
Member
54 Points
65 Posts
Re: Injecting the session into a wrapper class
Aug 13, 2010 09:09 PM|LINK
So I figured it out, what my problem was that I had tried so many types for the constructor and abstract class, but I didn't take enough time to figure out why the one I thought should work didn't work.
Currently, HttpSessionState does not derive from HttpSessionStateBase. So you cannot simply cast from HttpSessionState to HttpSessionStateBase. So to handle this, Microsoft had introduced the HttpSessionStateWrapper to allow casting this way. BUT, you cannot cast the other way since the session may not always be available.
Here is what I ended up figuring out:
public SessionVars() : this( new HttpSessionStateWrapper(HttpContext.Current.Session) ) { } public SessionVars(HttpSessionStateBase sessionWrapper) { Session = sessionWrapper; } public HttpSessionStateBase Session { get; private set; }I can use the new HttpSessionStateWrapper(HttpContext.Current.Session) to cast the current session to the HttpSessionStateBase, which can be used to serve up fake sessions and real ones.