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

时间:2018-07-27 21:04:45

标签: c# unit-testing asp.net-web-api httpcontext

我无法对包含HttpContext.Current.Request.LogonUserIdentity.Name的功能之一进行单元测试

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

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

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

如何为LogonUserIdentity分配值,以便测试功能?

5 个答案:

答案 0 :(得分:3)

这预示着更大的问题。

  

LogonUserIdentity属性将WindowsIdentity对象的属性和方法公开给当前连接到Microsoft Internet信息服务(IIS)的用户。 LogonUserIdentity公开的WindowsIdentity类的实例跟踪IIS请求令牌,并为在ASP.NET内部处理的当前HTTP请求提供对此令牌的轻松访问。 会自动创建WindowsIdentity类的实例,因此无需构造即可获取其方法和属性。

Source (强调我的)

  

如何为LogonUserIdentity分配值,以便测试功能?

不能。由于IIS不可用,因此不在单元测试中。

避免将您的代码与无法控制的无法测试的代码紧密结合在一起,例如HttpContextSystem.Web名称空间的大部分。

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

答案 1 :(得分: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() }
            );

答案 2 :(得分: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

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

我花了很多时间尝试模拟HttpContext或HttpContextBase,然后尝试使用伪造的WindowsIdentity类或HttpRequest.LogonUserIdentity属性进行填充。 什么都行不通-不需要完全模拟的HttpContext,因为您希望看到真实的响应,而不是返回模拟设置。 只是不会为WindowsIdentity类(“由于内部限制”)和LogonUserIdentity属性(在伪造消息中没有给出原因,只是不存在)而生成垫片。

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

我能够在伪造的请求包装程序中覆盖LogonUserIdentity属性,并在其中设置所需的内容。