Tobias
Tobias

Reputation: 2985

Unit Test Controller Session Variables in MVC3

I am unit testing my controller.

In one of my controller methods I am setting Session variables:

 public void Index(){
      Session["foo"] = "bar";

      return View();
 }

How can I unit test this? The problem is that the Session property is null when testing. Injecting is not possible because the Session property is readonly.

 [TestMethod]
 public void TestIndex()
     // When
     _controller.Index();

     // Then
     Assert.AreEqual("bar", _controller.Session["foo"])

Upvotes: 4

Views: 5094

Answers (3)

Andrey
Andrey

Reputation: 1248

I always recommend wrapping the session object in another object. This not only gives you an easier way to test, but also makes all access to the session type safe. It is very easy to mistype a session key name in one spot in one place and then hunt for the bug for hours.

The object would have fields as

public Foo{
    get{return Session["Foo"];}
    set{Session["Foo"]=value;}  
}

Once you are testing you can mock the session class with a dummy that only keeps state for the test.

The way I usually handle this is with dependency injection. How to set this up is a long examination. Here is a link to one way http://weblogs.asp.net/shijuvarghese/archive/2011/01/21/dependency-injection-in-asp-net-mvc-3-using-dependencyresolver-and-controlleractivator.aspx

Upvotes: 2

Ra Truong
Ra Truong

Reputation: 31

This is what I used for Unit Test friendly Session Caching. By checking HttpContext.Current for null, you're by passing the caching for nunit tests and still allow your program to function normally.

This is the simplest solution without making a lot of code changes in your project.

internal class SessionCache
{
    public static void Store(string key, object val) {
        if (HttpContext.Current != null) {
            HttpContext.Current.Session[key] = val;
        }
    }

    public static object Retrieve(string key) {
        if (HttpContext.Current != null) {
            return HttpContext.Current.Session[key];
        }

        return null;
    }
}

Upvotes: 3

Darin Dimitrov
Darin Dimitrov

Reputation: 1038710

Personally I like using the MvcContrib TestHelper which mocks all the HTTP pipeline:

[TestMethod]
public void HomeController_Index_Action_Should_Store_Bar_In_Session()
{
    // arrange
    var sut = new HomeController();
    new TestControllerBuilder().InitializeController(sut);

    // act
    sut.Index();

    // assert
    Assert.AreEqual("bar", (string)sut.Session["foo"]);
}

Upvotes: 7

Related Questions