【问题标题】:How do I make a unit test to test a method that checks request headers?如何进行单元测试来测试检查请求标头的方法?
【发布时间】:2012-03-05 00:40:39
【问题描述】:

我对单元测试非常非常陌生,正在尝试为一个非常简单的方法编写测试:

public class myClass : RequireHttpsAttribute
{
    public override void OnAuthorization(AuthoizationContext filterContext)
    {
        var request = filterContext.HttpContext.Request;
        var header = Convert.ToBoolean(request.Headers["Special-Header-Name"]);

        if (!(header || request.IsSecureConnection))
        {
            HandleNonHttpsRequest(filterContext);
        }
    }
}

此方法继承自RequireHttpsAttribute,检查页面中是否存在某个标题,如果缺少或错误,并且页面不安全,则它将调用HandleNonHttpsRequest,否则它什么也不做.

我们正在使用 Moq 和 Nunit 进行测试。我找到了一些资源来帮助使用 Moq 构建 fakeHttpContext,但老实说,我不确定如何使用它或在我的单元测试中去哪里以确保伪造的 HttpContext 是否导致 HandleNonHttpsRequest 方法调用。

非常感谢有关此问题的任何指导。

【问题讨论】:

    标签: c# asp.net-mvc unit-testing nunit moq


    【解决方案1】:

    是的,我会使用最小起订量并创建一个 Mock<AuthorizationContext>。您需要一系列模拟对象来设置虚假请求,最值得注意的是指定虚假标头的 NameValueCollection。

    var request = new Mock<HttpRequestBase>();
    request.SetupGet(c => c.Headers).Return(new NameValueCollection{ /* initialize values here */});
    request.SetupGet(c => c.IsSecureConnection).Return(/*specify true or false depending on your test */);
    
    var httpContext = new Mock<HttpContextBase>();
    httpContext.SetupGet(c => c.Request).Return(request.Object);
    
    
    var filterContext = new Mock<AuthorizationContext>();
    filterContext.SetupGet(c => c.HttpContext).Return(httpContext.Object);
    
    var myclass = new myClass();
    myClass.OnAuthorization(filterContext.Object);
    

    (对不起,如果语法或用法略有偏差;从我的头顶开始这样做)

    您可能需要进入并模拟 HandleNonHttpsRequest 调用的 filterContext 上的任何其他成员。我对此有两个建议,因为如果您正在测试的方法在 filterContext 上做很多复杂的事情,有时会很麻烦:1)目视检查,如果足够直截了当,模拟所有调用的部分 2)创建 myClass.OnAuthorizationRequest,但除了对 HandleNonHttpsRequest 的调用之外,不要实现任何代码。继续运行测试并修复丢失/错误模拟的成员,直到测试通过。然后实现 OnAuthorizationRequest 的实际逻辑,测试和修复(冲洗重复)直到它通过。

    【讨论】:

      【解决方案2】:

      我在使用 ASP.NET MVC 4 时遇到了 the accepted solution 的问题。为了解决这个问题,我模拟了 http 上下文 Items 属性,否则 sut.OnAuthorization 导致对象未定义异常:

      MockHttpContext.Setup(x => x.Items)
          .Returns(new System.Collections.Generic.Dictionary<object, object>());
      

      【讨论】:

        【解决方案3】:
        // arrange
        var context = new Mock<HttpContextBase>();
        var request = new Mock<HttpRequestBase>();
        var headers = new NameValueCollection
        {
            { "Special-Header-Name", "false" }
        };
        request.Setup(x => x.Headers).Returns(headers);
        request.Setup(x => x.HttpMethod).Returns("GET");
        request.Setup(x => x.Url).Returns(new Uri("http://www.example.com"));
        request.Setup(x => x.RawUrl).Returns("/home/index");
        context.Setup(x => x.Request).Returns(request.Object);
        var controller = new Mock<ControllerBase>();
        
        var actionDescriptor = new Mock<ActionDescriptor>();
        var controllerContext = new ControllerContext(context.Object, new RouteData(), controller.Object);
        var filterContext = new AuthorizationContext(controllerContext, actionDescriptor.Object);
        var sut = new myClass();
        
        // act
        sut.OnAuthorization(filterContext);
        
        // assert
        Assert.IsInstanceOfType(filterContext.Result, typeof(RedirectResult));
        var redirectResult = (RedirectResult)filterContext.Result;
        Assert.AreEqual("https://www.example.com/home/index", redirectResult.Url);
        

        【讨论】:

        • 谢谢!这使我朝着正确的方向前进,以进行一些成功的测试。
        • 嗨,我在单元测试中也遵循了相同的模拟代码,但我得到了 filterContext.DisplayMode 的 NullReferenceException
        猜你喜欢
        • 2021-12-19
        • 2018-03-13
        • 1970-01-01
        • 1970-01-01
        • 2021-11-26
        • 1970-01-01
        • 2012-01-08
        • 1970-01-01
        • 2013-04-20
        相关资源
        最近更新 更多