单元测试 - 用户未登录的原因为什么测试总是失败。 c#使用模拟会话

时间:2018-01-18 07:10:11

标签: c# asp.net-mvc unit-testing mocking rhino-mocks

我已经回答了我自己的问题 我对单元测试很新。 我正在尝试执行非常基本的测试。的" /家庭/索引" 即可。但由于会话检查而失败。

SessionManager是一个存在于模型中的类。

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语句和它的身体而不是测试结果作为通过。

测试代码是。

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

以下是会话管理器类,我用它来维护会话

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

3 个答案:

答案 0 :(得分:1)

首先静态有时难以测试。所以你必须改变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
}

检查这两篇关于依赖注入的文章 https://docs.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

我基本上配置了所有需要ISessionManager的课程 SessionManager课程,我也将其配置为&#34; Singleton&#34;因此,对于需要它的所有控制器,您将拥有SessionManager的共享实例。

Bootstrapper class(从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类

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

测试课(看看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);
    }
}

答案 1 :(得分:0)

由于会话管理器,您的测试失败。这次会话管理器为空。对于单元测试,您需要提供会话管理器的虚假实现。为此,您需要学习DI以及如何模拟对象。

答案 2 :(得分:0)

我在没有依赖注射的情况下解决了我的问题。 解决方案在这里。 MVC 5来自NuGet包。就像在解决方案中使用主MVC Web项目一样。通过NuGet将MVC,moq,RhinoMock安装到您的Test项目中,您应该很高兴。 它对我有用,可以创建会话变量

  

会话[&#34;用户类型&#34;] =&#34; ADMIN&#34;

并创建当前用户。我已经生成了

  

SessionManager.CurrentUser =用户

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