添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

In LogOn() action method, if user is authenticated then the method will
redirect to user home page. Otherwise it will return LogOn View. To implement a unit testing for this controller action method, I want to mock User Identity. I wanted to share the mocked context I came up with and how to use it so that if you need to unit test your controller with authentication.

MockHttpContext Class

MockHttpContext.cs

using System.Web;
using System.Text;
using System.Web.Mvc;
using Moq;
namespace MyApp.UnitTest.MembershipServiceMock
   public class MockHttpContext
        #region Properties
        public Mock<HttpContextBase> Http { get; private set; }
        public Mock<HttpServerUtilityBase> Server { get; private set; }
        public Mock<HttpResponseBase> Response { get; private set; }
        public Mock<HttpRequestBase> Request { get; private set; }
        public Mock<HttpSessionStateBase> Session { get; private set; }       
        public HttpCookieCollection Cookies { get; private set; }
        #endregion

First, define set of properties that match the properties of HttpContext. The most important one is the HttpContextBase. This is where the user object comes from that handles authentication.

Next, we are going to create two constructors. The first being the default constructor that just instantiates all the mocked properties:

    #region Constructor
        public MockHttpContext()
            Http = new Mock<HttpContextBase>(MockBehavior.Loose);
            Server = new Mock<HttpServerUtilityBas(MockBehavior.Loose);
            Response = new Mock<HttpResponseBase>(MockBehavior.Loose);
            Request = new Mock<HttpRequestBase>(MockBehavior.Loose);
            Session = new 
                         Mock<HttpSessionStateBase(MockBehavior.Loose);
            Cookies = new HttpCookieCollection();
            Http.Setup(c => c.Request).Returns(Request.Object);
            Http.Setup(c => c.Response).Returns(Response.Object);
            Http.Setup(c => c.Server).Returns(Server.Object);
            Http.Setup(c => c.Session).Returns(Session.Object);
            Request.Setup(c => c.Cookies).Returns(Cookies);
            Response.Setup(c => c.Cookies).Returns(Cookies);
     #endregion

We are really just mocking the various pieces of the HttpContext so that if any of them are accessed they return an empty mocked object. This is just to be used to test normal controller operations where authentication is not needed. 

Mocking Authentication

We need another constructor that will setup authentication section. Some times we need to check whether the user have permission to access certain pages. That is, we need to check User.Identity.IsAuthenticated is true or false, based on this result we need to take some decision.

 public MockHttpContext(string user, bool isAuthenticated):this()
          Http.Setup(c => c.User.Identity.Name).Returns(user);
            Http.Setup(c => c.User.Identity.IsAuthenticated).Returns(isAuthenticated);

Above constructor mocks the user Identity, and also it set the user authentication value. Next step is we need to call mocking context class. We can add two static methods to the class that creates a controller context.

 #region StaticMethods
        public static ControllerContext SetFakeContext()
            return new ControllerContext
                HttpContext = new MockHttpContext().Http.Object
        public static ControllerContext SetFakeAuthenticatedContext(string user, bool authenticated)
            return new ControllerContext
                HttpContext = new MockHttpContext(user, authenticated).Http.Object                              
        #endregion

Unit Test for Controller Action Methods

So let’s see how to use our fake HttpContext on a controller so that we can go about testing them with and without authentication.

namespace MyApp.UnitTest.ControllerTest
    [TestClass]
   public class AccountControllerTest
        private AccountController controller;
        [TestInitialize]
        public void TestInit()
           controller= new AccountController { ControllerContext = MockHttpContext.SetFakeContext() };        
        [TestMethod]
        public void TestLogOnView()
            ControllerContext context = MockHttpContext.SetFakeAuthenticatedContext("TestUser", false);
            controller.ControllerContext = context;
            var result = controller.LogOn();
            Assert.IsNotNull(result);
            Assert.IsInstanceOfType(result, typeof(ViewResult));

TestInitialize attribute is used to run a function before execution of a test. Authentication details has given under TestMethod TestLogOnView.

Hope it will help you. Thanks 🙂