如何对 "HttpContext.Current.Request.LogonUserIdentity.Name" 进行单元测试?

How do I unit test "HttpContext.Current.Request.LogonUserIdentity.Name"?

我无法对包含 HttpContext.Current.Request.LogonUserIdentity.Name

的函数之一进行单元测试

我得到的错误是因为 LogonUserIdentity 为空。

我在单元测试中添加了这个,以便为 HttpContext.Current 设置一个值,因为它也是空的:

HttpContext.Current = new HttpContext(
            new HttpRequest("", "http://localhost:8609", ""),
            new HttpResponse(new StringWriter())
            );

How can I assign a value to LogonUserIdentity so that I can test my function?

这预示着更大的问题即将来临。

The LogonUserIdentity property exposes the properties and methods of the WindowsIdentity object for the currently connected user to Microsoft Internet Information Services (IIS). The instance of the WindowsIdentity class that is exposed by LogonUserIdentity tracks the IIS request token and provides easy access to this token for the current HTTP request being processed inside of ASP.NET. An instance of the WindowsIdentity class is automatically created so it does not need to be constructed to in order to gain access to its methods and properties.

Source (强调我的)

How can I assign a value to LogonUserIdentity so that I can test my function?

你不能。不在单元测试中,因为 IIS 不可用。

避免将您的代码与您无法控制的不可测试代码紧密耦合,例如 HttpContext 和大多数 System.Web 命名空间。

相反,将它们封装在您控制的抽象之后并可以模拟。

您可以模拟上下文,如下所示

    var requestMock = new Mock<HttpRequestBase>();
    var contextMock = new Mock<HttpContextBase>();
    var mockIIdentity = new Mock<IIdentity>();
    mockIIdentity.SetupGet(x => x.Name).Returns("MyName");
    WindowsIdentity windowsIdentity = mockIIdentity.Object as WindowsIdentity;
    requestMock.Setup(x => x.LogonUserIdentity).Returns(windowsIdentity);
    contextMock.Setup(x => x.Request).Returns(requestMock.Object);


    yourControllerInstance.ControllerContext new  ControllerContext(contextMock.Object, new RouteData(), yourControllerInstance)

我也有一个自己写的测试助手,你可以在Github找到它并尝试使用它,你可以修改它以合并上面的设置https://github.com/danielhunex/TestHelper

您可以像这样使用 (System.Web.Fakes) 模拟它:

ShimHttpRequest.AllInstances.LogonUserIdentityGet = (a) => { return WindowsIdentity.GetCurrent(); };

我花了很多时间尝试模拟 HttpContext 或 HttpContextBase,然后尝试使用伪造的 WindowsIdentity class 或 HttpRequest.LogonUserIdentity 属性 填充。 没有任何效果——您不需要完全模拟的 HttpContext,因为您希望看到真实的响应,而不是返回的模拟设置。 填充码不会为 WindowsIdentity class ("due to internal limitations") 和 LogonUserIdentity 属性 生成(假消息中没有给出原因,它只是不存在)。

此处描述了如何通过请求和响应获得可测试的 HttpContext 的最佳方法: http://jonlanceley.blogspot.com/2015/08/unit-testing-part-2-faking-httpcontext.html

我能够在我的假请求包装器中覆盖 LogonUserIdentity 属性 并在那里设置我需要的任何东西。

不是最好的模拟,但有时你会被困住。

在此解决方案中,您必须在控制器上处理本地登录的用户 (johndoe) and/or 在你的数据库中。

但有效。

            var mockRequest = new HttpRequest("", "http://tempuri.org", "");
            HttpContext.Current = new HttpContext(
                mockRequest,
                new HttpResponse(new StringWriter())
            );

            mockRequest.GetType().InvokeMember(
                "_logonUserIdentity", 
                System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.SetField | System.Reflection.BindingFlags.Instance, 
                System.Type.DefaultBinder,
                mockRequest,
                new object[] { WindowsIdentity.GetCurrent() }
            );