views:

204

answers:

1

Hi folks,

I currently use the following approach to create a strongly typed object representing session variables.

public abstract class SessionController : Controller
{
    private const string SESSION_NAME = "UserSession";

    public SessionData SessionData
    {
        get
        {
            SessionData sessionData = (SessionData)Session[SESSION_NAME];

            if (sessionData != null)
            {
                return sessionData;
            }
            else
            {
                sessionData = new SessionData();
                Session[SESSION_NAME] = sessionData;

                return sessionData;
            }
        }
        set
        {
            Session[SESSION_NAME] = value;
        }
    }  
}

SessionData is a simple object like for example

[Serializable]
public class SessionData
{
    public String SessionId { get; set; }
    public Int64 UserId { get; set; }
    public String NameOfUser { get; set; }
}

When creating a new Controller I derivate it from the SessionController so that I have strongley typed access to my SessionData. For example

public CityController : SessionController
{
    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult Index()
    {
        ViewData.Model = _cityService.GetAll(SessionData.UserId);

        return View("Index");
    }
}

So, I am struggling at the moment to get this approached covered by a unittest. A shortened version of what I have tried is the following snippet

[SetUp]
public void SetUp()
{
    mocks = new MockRepository();
    _cityService = MockRepository.GenerateStub<ICityService>();
    _sesssionData = new SessionData { UserId = 1, SessionId = "1" };

    // First Approach
    controller = new CityController(_cityService);
    controller.Expect(p => p.SessionData).Return(_sesssionData);

    // Second Approach
    cctx = MockRepository.GenerateStub<ControllerContext>();
    cctx.Expect(p=>p.HttpContext.Session["UserSession"] as SessionData).Return(_sesssionData);
    controller.ControllerContext = cctx;
}

Has anyone a tip on how to get this problem solved?

A: 

If you make your SessionData property virtual then your first approach could work:

// Arrange
var mocks = new MockRepository();
var cityService = MockRepository.GenerateStub<ICityService>();
var sesssionData = new SessionData { UserId = 1, SessionId = "1" };
var controller = mocks.PartialMock<CityController>(cityService);
controller.Expect(c => c.SessionData).Return(sessionData);
controller.Replay();

// Act
controller.Index();

//Assert
...

IMO this approach is not very good because the SUT (Subject Under Test => in this case CityController) is being mocked with PartialMock.

Darin Dimitrov
Thanks for the hint and the Code Snippet. That worked like a charm. I know that this isn't the best approach, but its working. I don't want to change the whole infrastructure of my current codebase, so I'll use it.
Gordon