Asp.net mvc 如何使用ASP.NET MVC的MOQ模拟Request.ServerVariables?

Asp.net mvc 如何使用ASP.NET MVC的MOQ模拟Request.ServerVariables?,asp.net-mvc,unit-testing,moq,Asp.net Mvc,Unit Testing,Moq,当我开始学习mock和其他框架时,我正在学习为我的asp.NETMVC进行单元测试 经过检查,我发现最低起订量似乎是最容易获得的。 到目前为止,我一直在尝试模拟Request.ServerVariables,因为我已经了解到最好将它们抽象到属性中 因此: /// <summary> /// Return the server port /// </summary> protected string ServerPort

当我开始学习mock和其他框架时,我正在学习为我的asp.NETMVC进行单元测试

经过检查,我发现最低起订量似乎是最容易获得的。 到目前为止,我一直在尝试模拟Request.ServerVariables,因为我已经了解到最好将它们抽象到属性中

因此:

/// <summary>
        /// Return the server port
        /// </summary>
        protected string ServerPort
        {
            get
            {
                return Request.ServerVariables.Get("SERVER_PORT");
            }
        }
问题:
  • 到现在为止,我仍然是空的 运行时出现异常错误 测试。那么我在这里错过了什么
  • 如果我使用mvcmockhelpers 同学们,我怎么还能打电话给 request.verifyall功能以确保 所有模拟都正确设置了吗

  • 所以基本上我已经输入了所有的引用,并且使用这个函数我能够让它工作。我还没有使用mvcmockhelpers类,因为我仍在尝试学习所有这些

    对于任何有兴趣了解我是如何解决这个问题的人,这就是我使用的代码

    [Test]
    public void Create_Returns_ViewResult_On_Success() 
    {
      var server = new Mock<HttpServerUtilityBase>(MockBehavior.Loose);
      var response = new Mock<HttpResponseBase>(MockBehavior.Strict);
    
      var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
      request.Setup(x => x.ApplicationPath).Returns("/");
      request.Setup(x => x.Url).Returns(new Uri("http://localhost"));
      request.Setup(x => x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection{
        { "SERVER_NAME", "localhost" },
        { "SCRIPT_NAME", "localhost" },
        { "SERVER_PORT", "80" },
        { "HTTPS", "www.melaos.com" },
        { "REMOTE_ADDR", "127.0.0.1" },
        { "REMOTE_HOST", "127.0.0.1" }
      });
    
      var context = new Mock<HttpContextBase>();
      context.SetupGet(x => x.Request).Returns(request.Object);
      context.SetupGet(x => x.Response).Returns(response.Object);
      context.SetupGet(x => x.Server).Returns(server.Object);
    
      var controller = new HomeController();
      //MvcMockHelpers.SetFakeControllerContext(controller);
      controller.ControllerContext = new ControllerContext(context. Object, new RouteData(), controller);
    
      var results = controller.Create();
      Assert.IsNotNull(results);
      Assert.IsInstanceOf(typeof(ViewResult), results);
    }
    
    [测试]
    public void Create_在_Success()上返回_ViewResult_
    {
    var server=newmock(MockBehavior.Loose);
    var响应=新模拟(MockBehavior.Strict);
    var request=newmock(MockBehavior.Strict);
    Setup(x=>x.ApplicationPath)。返回(“/”;
    Setup(x=>x.Url).Returns(新Uri(“http://localhost"));
    request.Setup(x=>x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection{
    {“服务器名称”,“本地主机”},
    {“脚本名称”,“本地主机”},
    {“服务器端口”,“80”},
    {“HTTPS”,“www.melaos.com”},
    {“远程地址”,“127.0.0.1”},
    {“远程主机”,“127.0.0.1”}
    });
    var context=newmock();
    SetupGet(x=>x.Request).Returns(Request.Object);
    SetupGet(x=>x.Response).Returns(Response.Object);
    SetupGet(x=>x.Server).Returns(Server.Object);
    var controller=新的HomeController();
    //MvcMockHelpers.SetFakeControllerContext(控制器);
    controller.ControllerContext=新的ControllerContext(context.Object,new RouteData(),controller);
    var results=controller.Create();
    Assert.IsNotNull(结果);
    Assert.IsInstanceOf(typeof(ViewResult),results);
    }
    
    因为我想模拟HttpContext,而不是HttpContextBase,所以我试图找到一种方法将HttpContextBase模拟对象转换为HttpContext,但发现这是不可能的

    HttpContext

    这是经典的asp.net上下文。问题是它 没有基类且不是虚拟的,因此无法用于测试 (不能嘲笑它)。建议不要将其作为函数传递 参数,而是传递HttpContextBase类型的变量

    HttpContextBase

    这是(c#3.5的新版本)对HttpContext的替代。既然是 抽象地说,它现在是可以模仿的。这个想法是你的功能 expected to passed上下文应该期望接收其中一个。 它由HttpContextWrapper具体实现

    HttpContextWrapper

    在C#3.5中也是新的—这是 HttpContextBase。要在普通网页中创建其中一个,请使用“新建” HttpContextWrapper(HttpContext.Current)

    其思想是,为了使代码单元可测试,您需要声明所有 HttpContextBase类型的变量和函数参数,以及 使用IOC框架,如Castle Windsor,将其注入。正常情况下 代码,castle是注入“new”的等价物 HttpContextWrapper(HttpContext.Current)’,而在测试代码中 将获得HttpContextBase的模拟

    (来源:)

    所以我改变了调用代码的方式

    从使用HttpContext开始:

    public static string GetIpAddress(HttpContext currentContext) {
     ...
    }
    
    要使用
    HttpContextBase

    public static string GetIpAddress(HttpContextBase currentContext) {
     ...
    }
    
    当我使用该方法时,我用HttpContextWrapper包装HttpContext,如下所示:

    var ip = GeneralUtil.GetIpAddress(new HttpContextWrapper(HttpContext.Current));
    
    现在,您可以通过以下方式轻松模拟HttpContextBase

    var ip = GeneralUtil.GetIpAddress(new HttpContextWrapper(HttpContext.Current));