user5407401
user5407401

Reputation:

Unit Test -- user not logged in that's why test always Results as fail. c# using mock session

I Have Answered My own Question i am fairly new to unit test. i am trying perform very basic test. "/home/Index". but it fails due to session check.

SessionManager is a class which exists in model.

using EPS.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace EPS.Controllers
{

    public class HomeController : Controller
    {

        public ActionResult Index()
        {

            if (!SessionManager.IsUserLoggedIn || SessionManager.CurrentUser.EmployeeId == 0)
            {
                return RedirectToAction("Index", "Login");
            }
            else if (Session["UserType"] == "ADMIN")
            {
                return View(); //we have to run this view than test will pass
            }
            else
                return HttpNotFound();
        }
}

if i comment if statement and it body than test result as pass.

test code is.

using EPS;
using EPS.Models;
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using MvcContrib.TestHelper;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Mail;
using FakeHttpContext;
using System.Web;
using System.Web.Mvc;
using EPS.Controllers;

namespace EPS.test
{
    [TestClass]
    public class ControllerTest
    {

        [TestMethod]
        public void Index()
        {           
            //arrange
            HomeController controller = new HomeController();
           //Act
            ViewResult result= controller.Index() as ViewResult;
            //Assert
            Assert.IsNotNull(result);
        }
    }
}

Here is Session Manger Class which i am using to maintain session

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using System.Collections;

namespace EPS.Models
{
    public static class SessionManager
    {
        #region Private Data

        private static String USER_KEY = "user";

        #endregion

        public static Employee CurrentUser
        {
            get;
            set;
        }
        public static string UserType
        {
            get;
            set;
        }
        public static Int32 SessionTimeout
        {
            get
            {
                return System.Web.HttpContext.Current.Session.Timeout;
            }
        }

        public static String GetUserFullName()
        {
            if (SessionManager.CurrentUser != null)
                return SessionManager.CurrentUser.FirstName;
            else
                return null;
        }
        public static Boolean IsUserLoggedIn
        {
            get
            {
                if (SessionManager.CurrentUser != null)
                    return true;
                else
                    return false;
            }
        }
        #region Methods
        public static void AbandonSession()
        {
            for (int i = 0; i < System.Web.HttpContext.Current.Session.Count; i++)
            {
                System.Web.HttpContext.Current.Session[i] = null;
            }
            System.Web.HttpContext.Current.Session.Abandon();
        }

        #endregion
    }
}

Upvotes: 0

Views: 605

Answers (3)

user5407401
user5407401

Reputation:

i have solved my problem without Dependency Injections. solution is here. MVC 5 comes in from a NuGet package. Just as it did with the main MVC web project in your solution. Install MVC,moq,RhinoMock via NuGet into your Test project, and you should be good to go. it worked for me to create session variable

Session["Usertype"]="ADMIN"

and by creating a current user. i have generated a

SessionManager.CurrentUser=user

true

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MyUnitTestApplication;
using MyUnitTestApplication.Controllers;
using MyUnitTestApplication.Models;
using Moq;
using System.Security.Principal;
using System.Web;
using System.Web.Routing;
//using Rhino.Moq;
using Rhino.Mocks;


 namespace MyUnitTestApplication.Tests.Controllers
    {
        [TestClass]
        public class HomeControllerTest
        {
            [TestMethod]
            public void TestActionMethod()
            {
                Employee User = new Employee();
                User.FirstName = "Ali";
                User.EmployeeId = 1;
                SessionManager.CurrentUser = User;
     var fakeHttpContext = new Mock<HttpContextBase>();
      var sessionMock = new Mock<HttpSessionStateBase>();
                sessionMock.Setup(n => n["UserType"]).Returns("ADMIN");
                sessionMock.Setup(n => n.SessionID).Returns("1");
     fakeHttpContext.Setup(n => n.Session).Returns(sessionMock.Object);
     var sut = new HomeController();
                sut.ControllerContext = new ControllerContext(fakeHttpContext.Object, new RouteData(), sut);
                ViewResult result = sut.TestMe() as ViewResult;
                Assert.AreEqual(string.Empty, result.ViewName);
    }
    }
    }

Upvotes: 0

Hugo Jose
Hugo Jose

Reputation: 369

first of all statics sometimes is difficult to test. so you must change SessionManager

public class SessionManager : ISessionManager
{
    #region Private Data

    private static String USER_KEY = "user";

    #endregion

    public Employee CurrentUser
    {
        get
        {
            return (Employee)System.Web.HttpContext.Current.Session[USER_KEY];
        }
    }
    public string UserType
    {
        get { return (string) System.Web.HttpContext.Current.Session["USER_TYPE"]; }
    }
    public Int32 SessionTimeout
    {
        get
        {
            return System.Web.HttpContext.Current.Session.Timeout;
        }
    }

    public String GetUserFullName()
    {
        if (CurrentUser != null)
            return CurrentUser.FirstName;
        else
            return null;
    }
    public Boolean IsUserLoggedIn
    {
        get
        {
            if (CurrentUser != null)
                return true;
            else
                return false;
        }
    }
    #region Methods
    public void AbandonSession()
    {
        for (int i = 0; i < System.Web.HttpContext.Current.Session.Count; i++)
        {
            System.Web.HttpContext.Current.Session[i] = null;
        }
        System.Web.HttpContext.Current.Session.Abandon();
    }

    #endregion
}

check this two article about Dependency injections https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/hands-on-labs/aspnet-mvc-4-dependency-injection

https://msdn.microsoft.com/en-us/library/ff647854.aspx

I basically configured all class that need ISessionManager to be fill up with SessionManager class and also I configured it to be "Singleton" so you will have shared instance of SessionManager for all controller that need it.

Bootstrapper class(initialize it on from your App_Start)

public static class Bootstrapper
{
    public static IUnityContainer Initialise()
    {
        var container = BuildUnityContainer();

        DependencyResolver.SetResolver(new UnityDependencyResolver(container));

        return container;
    }

    private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer();

        // register all your components with the container here
        // it is NOT necessary to register your controllers

        // e.g. container.RegisterType<ITestService, TestService>();   

        RegisterTypes(container);

        return container;
    }

    public static void RegisterTypes(IUnityContainer container)
    {
        // Singleton lifetime.   
        container.RegisterType<ISessionManager, SessionManager>(new ContainerControlledLifetimeManager());
    }
}

HomeController class

public class HomeController : Controller
{
    private readonly ISessionManager _sessionManager;

    public HomeController(ISessionManager sessionManager)
    {
        _sessionManager = sessionManager;
    }

    public ActionResult Index()
    {

        if (!_sessionManager.IsUserLoggedIn || _sessionManager.CurrentUser.EmployeeId == 0)
        {
            return RedirectToAction("Index", "Login");
        }
        else if (_sessionManager.UserType == "ADMIN")
        {
            return View(); //we have to run this view than test will pass
        }
        else
            return HttpNotFound();
    }
}

Test class (take a look on https://github.com/Moq/moq4/wiki/Quickstart)

[TestClass()]
public class HomeControllerTests
{
    [TestMethod()]
    public void IndexTest()
    {
        // Arrange
        Employee user = new Employee()
        {
            EmployeeId = 1,
            FirstName = "Mike"
        };
        var simulatingLoggedUser = new Mock<ISessionManager>();
        simulatingLoggedUser.Setup(x => x.CurrentUser).Returns(user);
        simulatingLoggedUser.Setup(x => x.UserType).Returns("ADMIN");
        simulatingLoggedUser.Setup(x => x.IsUserLoggedIn).Returns(true);

        HomeController homeController = new HomeController(simulatingLoggedUser.Object);

        // Act
        var result = homeController.Index() as ViewResult;

        //Assert
        Assert.IsNotNull(result);
    }
}

Upvotes: 1

Ehasanul Hoque
Ehasanul Hoque

Reputation: 640

Your test is failing due to session manager. This time Session Manager is null. For unit test, you need to supply fake implementation of Session Manager. For doing this, you need to learn DI and how to mock a object.

Upvotes: 0

Related Questions