views:

98

answers:

2

I'm trying to figure out how to unit test my object that persists itself to session state.

The controller does something like...

    [HttpPost]
    public ActionResult Update(Account a)
    {
        SessionManager sm = SessionManager.FromSessionState(HttpContext.Current.Session);
        if ( a.equals(sm.Account) )
          sm.Account = a;
        return View("View", a);
    }

And the session manager serializes itself to session state

public class SessionManager
    {
        public static SessionManager FromSessionState(HttpSessionStateBase state)
        {
            return state["sessionmanager"] as SessionManager ?? new SessionManager();
        }

        public Guid Id { get; set; }
        public Account Account { get; set; }
        public BusinessAssociate BusinessAssociate {get; set; }
    }

I'm thinking that there are two approaches to unit testing...

  1. in the static instantiator pass in the session state reference and then restore from that. this would allow me to mock this parameter and everything would be golden.

    public static SessionManager FromSessionState(HttpSessionStateWrapper session) { return session["sessionmanager"] as SessionManager ?? new SessionManager(); }

  2. create a mock for the SessionManager and use that for testing of the controller.

A: 

Currently this controller action is very difficult to unit test as it calls a static method that is relying on HttpContext.Current. While the first approach seems to work in the second you still need to pass the session state somewhere so that the manager could work with it. Also don't pass HttpSessionStateWrapper, use HttpSessionStateBase instead.

Darin Dimitrov
That is good advice. I've been having a hard time writing the unit tests, so anything to make it simpler is good. I was also toying with the idea of having a separate class that would be used to persist the session manager to the session state. I thought that might separate the concerns so that session manager just stores my temporary objects and then the sessionrepository would be responsible for persisting it.
yamspog
A: 

Here's an idea: Create a session manager "persistence" interface:

public interface ISessionManagerPersist
{
    SessionManager Load();
    void Save(SessionManager sessionManager);
}

Create an HTTPSession-based implementation of your persistence:

public class SessionStatePersist : ISessionManagerPersist
{
    public SessionManager Load()
    {
        return HttpContext.Current.Session["sessionmanager"] as SessionManager ?? new SessionManager();
    }

    public void Save(SessionManager sessionManager)
    {
        HttpContext.Current.Session["sessionmanager"] = sessionManager;
    }
}

Now make your controller have a dependency on ISessionManagerPersist. You can inject a stub ISessionManagerPersist during testing and use the session-based one during production. This also has the benefit of not needing changes if you decided to persist somewhere else (like a DB or something). Just implement a new ISessionManagerPersist.

Patrick Steele