How do I unit test a controller action that uses ther Controller.User variable?

后端 未结 2 710
轮回少年
轮回少年 2021-02-20 09:43

I have a controller action that automatically redirects to a new page if the user is already logged in (User.Identity.IsAuthenticated). What is the best way to writ

2条回答
  •  北海茫月
    2021-02-20 10:31

    I've been using the following Mocks with Moq to allow setting up various conditions in my unit tests. First, the HttpContextBase mock:

        public static Mock GetHttpContextMock(bool isLoggedIn)
        {
            var context = new Mock();
            var request = new Mock();
            var response = new Mock();
            var session = new Mock();
            var server = new Mock();
            var principal = AuthenticationAndAuthorization.GetPrincipleMock(isLoggedIn);
    
            context.SetupGet(c => c.Request).Returns(request.Object);
            context.SetupGet(c => c.Response).Returns(response.Object);
            context.SetupGet(c => c.Session).Returns(session.Object);
            context.SetupGet(c => c.Server).Returns(server.Object);
            context.SetupGet(c => c.User).Returns(principal.Object);
    
            return context;
        }
    

    Every property that might provide a useful Mock is set up in here. That way, if I need to add something like a referrer, I can just use:

    Mock.Get(controller.Request).Setup(s => s.UrlReferrer).Returns(new Uri("http://blah.com/");
    

    The "GetPrincipleMock" method is what sets up the user. It looks like this:

        public static Mock GetPrincipleMock(bool isLoggedIn)
        {
            var mock = new Mock();
    
            mock.SetupGet(i => i.Identity).Returns(GetIdentityMock(isLoggedIn).Object);
            mock.Setup(i => i.IsInRole(It.IsAny())).Returns(false);
    
            return mock;
        }
    
        public static Mock GetIdentityMock(bool isLoggedIn)
        {
            var mock = new Mock();
    
            mock.SetupGet(i => i.AuthenticationType).Returns(isLoggedIn ? "Mock Identity" : null);
            mock.SetupGet(i => i.IsAuthenticated).Returns(isLoggedIn);
            mock.SetupGet(i => i.Name).Returns(isLoggedIn ? "testuser" : null);
    
            return mock;
        }
    

    Now, my controller setups in the tests look like this:

    var controller = new ProductController();
    var httpContext = GetHttpContextMock(true); //logged in, set to false to not be logged in
    
    ControllerContext controllerContext = new ControllerContext(httpContext.Object, new RouteData(), controller);
    controller.ControllerContext = controllerContext;
    

    It's a little bit of verbose setup, but once you have everything in place, testing a variety of conditions becomes a lot easier.

提交回复
热议问题