单元测试——用户未登录,这就是测试总是失败的原因。 c# 使用模拟会话

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

我已经回答了我自己的问题 我对单元测试还很陌生。 我正在尝试执行非常基本的测试。 "/home/Index"。但由于会话检查而失败。

SessionManager 是模型中存在的class。

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

这是 Session Manger Class 我用它来维护会话

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

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

首先,静力学有时很难测试。所以你必须改变 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填充的class SessionManager class 而且我将其配置为 "Singleton" 因此您将为所有需要它的控制器共享 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());
    }
}

家庭控制器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();
    }
}

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

我已经在没有依赖注入的情况下解决了我的问题。 解决方案在这里。 MVC 5 来自 NuGet 包。就像它对解决方案中的主要 MVC Web 项目所做的那样。通过 NuGet 将 MVC、moq、RhinoMock 安装到您的测试项目中,您应该可以开始了。 它对我有用,可以创建会话变量

Session["Usertype"]="ADMIN"

并通过创建当前用户。我生成了

SessionManager.CurrentUser=user

正确

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