4

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"])

3 Answers 3

7

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"]);
}
Sign up to request clarification or add additional context in comments.

2 Comments

WHat about ASP.NET MVC5 ? As I can read MvcContrib TestHelper system requirements says FOR USE ASP.Net MVC 1 or ASP.Net MVC 2 or ASP.Net MVC 3 FOR DEVELOPMENT .Net 3.5 SP1 or .Net 4.0
I'm also interested in Clark Kent's question. MvcContrib does not seem to be updated for quite some time now. Can I safely use the classes in the TestHelper namespace in an MVC 5 project?
3

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;
    }
}

Comments

2

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

1 Comment

can you post an example please?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.