代码之家  ›  专栏  ›  技术社区  ›  Jedidja

如何对使用ther controller.User变量的控制器操作进行单元测试?

  •  9
  • Jedidja  · 技术社区  · 16 年前

    我有一个控制器操作,如果用户已经登录,它会自动重定向到新页面( User.Identity.IsAuthenticated )。为该场景编写单元测试以确保重定向发生的最佳方法是什么?

    2 回复  |  直到 16 年前
        1
  •  20
  •   mkedobbs    16 年前

    我一直在使用以下Moq模拟,以允许在单元测试中设置各种条件。首先,HttpContextBase模拟:

        public static Mock<HttpContextBase> GetHttpContextMock(bool isLoggedIn)
        {
            var context = new Mock<HttpContextBase>();
            var request = new Mock<HttpRequestBase>();
            var response = new Mock<HttpResponseBase>();
            var session = new Mock<HttpSessionStateBase>();
            var server = new Mock<HttpServerUtilityBase>();
            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;
        }
    

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

    “GetPrincipleMock”方法是设置用户的方法。看起来是这样的:

        public static Mock<IPrincipal> GetPrincipleMock(bool isLoggedIn)
        {
            var mock = new Mock<IPrincipal>();
    
            mock.SetupGet(i => i.Identity).Returns(GetIdentityMock(isLoggedIn).Object);
            mock.Setup(i => i.IsInRole(It.IsAny<string>())).Returns(false);
    
            return mock;
        }
    
        public static Mock<IIdentity> GetIdentityMock(bool isLoggedIn)
        {
            var mock = new Mock<IIdentity>();
    
            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;
        }
    

    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;
    

    这是一个有点冗长的设置,但是一旦你准备好了一切,测试各种条件就变得容易多了。

        2
  •  9
  •   Mark Seemann    16 年前

    var user = new GenericPrincipal(new GenericIdentity(string.Empty), null);
    var httpCtxStub = new Mock<HttpContextBase>();
    httpCtxStub.SetupGet(ctx => ctx.User).Returns(user);
    
    var controllerCtx = new ControllerContext();
    controllerCtx.HttpContext = httpCtxStub.Object;
    
    sut.ControllerContext = controllerCtx;
    

    然后调用您的操作并验证返回结果是否为重定向结果。

    此测试利用了一个隐含的知识,即当您使用空名称创建GenericEntity时,它将为IsAuthenticated返回false。您可以考虑通过使用 Mock<IIdentity>