Adam Bartz
Adam Bartz

Reputation: 249

Unable to set session variable

I have been unsuccessful in attempting to set a session variable in order to run some unit tests. I keep getting the error of "System.NullReferenceException: Object reference not set to an instance of an object" when I attempt to set my session variable.

Here is the test I'm building:

[TestMethod]
public void MyMethod()
{
  //Arrange
  int id = 12345;
  string action = "A";
  string comment = "";
  string user = "user";
  var controller = new MyController();

  //Act
  controller.Session["altUser"] = user;
  var result = controller.Process(id, action, comment);

  //Assert
  Assert.IsNotNull(result);     
}

And here is my controller:

[Authorize]
public class MyController : Controller
{
  public ActionResult Process(int id, string action, string comment)
  {
    string userId = Session["altUser"].ToString();
    //some other stuff that evaluates ID, Action, and Comment
  }
}

However, when I run the application itself, there are no errors and the application functions as it should. I do understand that with Test Driven Development the tests should pave the way for the implementation. I am trying to get some practice with Unit Testing on applications that have already been done. If at all possible, since the application works, I would like to avoid making any changes to my implementation and just write a unit test to support what I already know.

Upvotes: 3

Views: 5020

Answers (3)

Colin Mackay
Colin Mackay

Reputation: 19175

The controller gets the session from the HttpContext, which does not exist in your unit test, which is why it fails.

You can, however, mock an HttpContext and put a mock session in there too.

Something like this might work (uses moq as the Mocking framework)

    var mockControllerContext = new Mock<ControllerContext>();
    var mockSession = new Mock<HttpSessionStateBase>();
    mockSession.SetupGet(s => s["altUser"]).Returns("user");
    mockControllerContext.Setup(p => p.HttpContext.Session).Returns(mockSession.Object);

    var controller = new MyController();
    controller.ControllerContext = mockControllerContext.Object;

You'll obviously need to fill the mock object with the details of what you actually want to get out.

You can also derive your own classes from HttpSessionStateBase and HttpContextBase and use them instead of the real session.

Upvotes: 8

Ondrej Tucny
Ondrej Tucny

Reputation: 27962

There is no spoon, er, session — the ASP.NET runtine is neither initialized nor running when you execute the unit test. You should decompose any Session dependencies outside your code and make the classes and methods you need to unit test independent of ASP.NET's runtime features.

Upvotes: 2

Greg Smith
Greg Smith

Reputation: 2469

When you run the unit test, you're not running the program via a web server, and therefore do not have access to any HttpContext, or ASP.NET session, whereas when you run the program via debug in VS, you are using the built in Visual Studio web server, which enables the program to use the session.

Here is an article which walks you through the ASP.NET session and how it works.

Upvotes: 0

Related Questions