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

3

我无法对包含HttpContext.Current.Request.LogonUserIdentity.Name的函数进行单元测试。

出现错误的原因是LogonUserIdentity为空。

为了解决这个问题,我在我的单元测试中添加了以下代码以为HttpContext.Current设置一个值:

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

我该如何为LogonUserIdentity赋值,以便测试我的函数?

如果你正在进行单元测试,你可以模拟它。 - Dan Hunex
@DanHunex 我该怎么做? - BStill
@DanHunex 我已经尝试过这个:https://dev59.com/UWkw5IYBdhLWcg3w1d4m#10126711 - BStill
@DanHunex 但它仍然不起作用。 - BStill
你需要模拟HttpContextBase。我会给你一个例子。 - Dan Hunex
5个回答

2
这是一个更大问题的标志即将到来。
LogonUserIdentity属性公开了当前连接用户的WindowsIdentity对象的属性和方法,用于Microsoft Internet Information Services(IIS)。由LogonUserIdentity公开的WindowsIdentity类的实例跟踪IIS请求令牌,并为正在ASP.NET中处理的当前HTTP请求提供对此令牌的简单访问。 WindowsIdentity类的实例自动创建,因此无需构造即可访问其方法和属性。 来源(我强调)
如何为LogonUserIdentity分配值以便测试我的函数?
你不能。在单元测试中无法使用IIS。
避免将代码与不可控制的不可测试代码(如HttpContext和System.Web命名空间的大部分)紧密耦合。相反,将它们封装在您可以控制并且可以模拟的抽象后面。

1
我花了很多时间尝试模拟HttpContext或HttpContextBase,然后尝试使用伪造的WindowsIdentity类或HttpRequest.LogonUserIdentity属性进行Shim。 什么都不起作用 - 您不需要完全模拟HttpContext,因为您想要看到真实的响应,而不是返回您的模拟设置。 Shims只是不能为WindowsIdentity类(“由于内部限制”)和LogonUserIdentity属性(在fakes消息中没有给出原因,它只是不存在)生成。 获取可测试的带有请求和响应的HttpContext的最佳方法在此处描述: http://jonlanceley.blogspot.com/2015/08/unit-testing-part-2-faking-httpcontext.html 我能够在我的虚拟请求包装器中覆盖LogonUserIdentity属性并设置任何我需要的内容。

1

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

在这个解决方案中,您必须在控制器和/或数据库中处理本地登录用户(johndoe)。

但它有效。

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

0

您可以按照此处所示的方式模拟上下文

    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


我正在尝试测试的控制器是一个 ApiController,所以我需要使用 new HttpControllerContext。我该怎么做?当我尝试使用它时,它会给我报错。 - BStill
感谢您的方法。我想将WindowsIdentity.Token设置为某个值。现在我能够使用这种方法做到这一点。 - harinimurugan

0
你可以使用 (System.Web.Fakes) 来模拟它,像这样:
ShimHttpRequest.AllInstances.LogonUserIdentityGet = (a) => { return WindowsIdentity.GetCurrent(); };

无法在httpRequest上为WindowsIdentity类或特定属性添加shim。 - amarax

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接