Reputation:
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
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
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
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