Pawan
Pawan

Reputation: 2218

How to do unit test for session values?

Below is piece of the code of controller method(c#) :-

public ActionResult SelectProduct(string ProdName, int Block, int ProductAddressId = 0)
{
       if (ProductAddressId == 0 && Block == 1 && System.Web.HttpContext.Current.Session["ReturnProductAddressID"] != null)
       {
           ProductAddressId = (int)System.Web.HttpContext.Current.Session["ReturnProductAddressID"]; 
       }
       //other stuffs………    
}

Below is unit test method :-

   [TestMethod]
   public void SelectProduct_Condition1_Test()
   {
       //Arrange
       var controller = new ProductController();

       var prodName = string.Empty;
       var block = 1;
       var productAddressId = 0;

   //section 1
       /*var mockControllerContext = new Mock<ControllerContext>();
       var mockSession = new Mock<HttpSessionStateBase>();
       mockSession.SetupGet(s => s["ReturnProductAddressID"]).Returns("1");
       mockControllerContext.Setup(p => p.HttpContext.Session).Returns(mockSession.Object);*/

  //section 2
       /*int sessionValue = 1;
       var mockControllerContext = new Mock<ControllerContext>();
       var mockSession = new Mock<HttpSessionStateBase>();
       mockSession.SetupSet(s => s["ReturnProductAddressID"] = It.IsAny<int>()).Callback((string name, object val) => sessionValue = (int)val);
       mockSession.SetupGet(s => s["ReturnProductAddressID"]).Returns(() => sessionValue);
       mockControllerContext.Setup(p => p.HttpContext.Session).Returns(mockSession.Object);*/

       //Act         
       var actual = controller.SelectProduct(prodName,block,productAddressId);
 }

I want to ask how can i test or mock the session value up side on my action method(in if condition) ?

I have tried certain things in section 1 and section 2(commented section in unit test method above).But nothing is working for that.

So can anyone let me know how to do unit test for sessions ?

EDIT:

Nothing the above stuff working instead of below :-

System.Web.HttpContext.Current.Session["ReturnProductAddressID"] = "12";

means if i set the session value directly in unit test method.But i want to know will it be correct approach ?

Upvotes: 8

Views: 10135

Answers (2)

Jaap Zwart
Jaap Zwart

Reputation: 1

To be honest: mocking Session vars or using 'the real deal' by hooking into the current session keeps being nasty to do. When having lots of HttpContext.Session vars in your code - yes, you can have an opinion about it - makes testing them 'hard' to do.

My solution is using ViewBags as much as possible and keep result values you want to test into those ViewBags and ignore the null errors from the HttpContext.Session vars. If you really want to test some of them and their values, put those values in ViewBags and test those in your viewResult.

By using proper try catches in my real code, the nulls on Session vars will be ígnored and when needed I'll check the values of ViewBags in viewResult.

Is this the best solution? Probably not, no, definitely not but it kept my pace going and solved the need: getting the controllers running and keeping an eye on the values I want in ViewBags.

Example code:

        // Arrange
        TarotCards.Controllers.ProverbsController controller = new 
        TarotCards.Controllers.ProverbsController();

        // Act
        ActionResult result = controller.IndexThrow("KeeperHelp");

        // Assert
        Assert.IsInstanceOfType(result, typeof(ViewResult));
        ViewResult viewResult = result as ViewResult;
        if (viewResult != null)
        {
            string sProverb = viewResult.ViewData["Proverb"].ToString();
            Assert.IsTrue(sProverb.Contains("Help on Keeper"));
            // Assert content of viewResult.
        }

Upvotes: 0

Ashwini Verma
Ashwini Verma

Reputation: 7525

You can use Mock. Here is how I have done before.

Download updated MoQ https://www.nuget.org/packages/moq

Moc session for the controller

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

Register mockControllerContext for controller

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

Finally Act

var actual = controller.SelectProduct(YourModel);

So, your code would be something like this.

    [TestMethod]
    public void SelectProduct_Condition1_Test()
    {
        var prodName = string.Empty;
        var block = 1;
        var productAddressId = 0;

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

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

        //Act         
        var actual = controller.SelectProduct(prodName, block, productAddressId);
    }

Upvotes: 18

Related Questions