【问题标题】:How to mock the Request.ServerVariables using MOQ for ASP.NET MVC?如何使用 ASP.NET MVC 的 MOQ 模拟 Request.ServerVariables?
【发布时间】:2011-02-15 17:59:19
【问题描述】:

我刚开始学习为我的 asp.net mvc 进行单元测试,当时我开始了解 mock 和现在存在的不同框架。

检查 SO 后,我发现 MOQ 似乎是最容易接受的。 到目前为止,我一直在尝试模拟 Request.ServerVariables,因为 after reading this post,我了解到最好将它们抽象为属性。

这样:

/// <summary>
        /// Return the server port
        /// </summary>
        protected string ServerPort
        {
            get
            {
                return Request.ServerVariables.Get("SERVER_PORT");
            }
        }

但是我很难学习如何正确地模拟这个。 我有一个家庭控制器 ActionResult 函数,它获取用户服务器信息并继续创建一个表单来获取用户信息。

我尝试使用hanselman's mvcmockhelpers class,但我不知道如何使用它。

这就是我目前所拥有的......

[Test]
        public void Create_Redirects_To_ProductAdded_On_Success() 
        {

            FakeViewEngine engine = new FakeViewEngine();

            HomeController controller = new HomeController();
            controller.ViewEngine = engine;

            MvcMockHelpers.SetFakeControllerContext(controller);

            controller.Create();

            var results = controller.Create();

            var typedResults = results as RedirectToRouteResult;

            Assert.AreEqual("", typedResults.RouteValues["action"], "Wrong action");
            Assert.AreEqual("", typedResults.RouteValues["controller"], "Wrong controller");
        }

问题:

  1. 到目前为止,我仍然是 null 我运行时出现异常错误 测试。那么我在这里缺少什么?
  2. 如果我使用 mvcmockhelpers 上课,我怎么还能打电话 request.verifyall 函数确保 所有的模拟都正确设置了吗?

【问题讨论】:

    标签: asp.net-mvc unit-testing moq


    【解决方案1】:

    所以基本上我已经输入了所有的参考资料,并且使用这个函数我能够让它工作。我还没有使用 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);
    }
    

    【讨论】:

      【解决方案2】:

      由于我想mock HttpContext,而不是HttpContextBase,所以我试图找到一种方法将HttpContextBase mock 对象转换为HttpContext,结果发现这是不可能的。

      HttpContext

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

      HttpContextBase

      这是 HttpContext 的(c# 3.5 的新功能)替换。因为它是 抽象的,它现在是可模拟的。这个想法是你的功能 期望被传递一个上下文应该期望接收其中之一。 具体由HttpContextWrapper实现

      HttpContextWrapper

      也是 C# 3.5 中的新功能 - 这是 HttpContextBase。要在普通网页中创建其中之一,请使用 new HttpContextWrapper(HttpContext.Current)。

      这个想法是为了让你的代码可单元测试,你声明你所有的 变量和函数参数的类型为 HttpContextBase,以及 使用 IOC 框架,例如 Castle Windsor 将其注入。在正常 代码,城堡是注入相当于'new HttpContextWrapper(HttpContext.Current)',而在测试代码中你是 得到一个 HttpContextBase 的模拟。

      (来源:http://www.splinter.com.au/httpcontext-vs-httpcontextbase-vs-httpcontext/

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

      来自使用HttpContext

      public static string GetIpAddress(HttpContext currentContext) {
       ...
      }
      

      使用HttpContextBase

      public static string GetIpAddress(HttpContextBase currentContext) {
       ...
      }
      

      当我使用该方法时,我用 HttpContextWrapper 包装 HttpContext,如下所示:

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

      现在您可以通过关注 Dan Atkinson's reply

      轻松模拟 HttpContextBase

      【讨论】:

        猜你喜欢
        • 2010-11-29
        • 1970-01-01
        • 2018-01-13
        • 2023-03-16
        • 2012-03-18
        • 2010-10-19
        • 2016-09-30
        • 2019-10-06
        • 1970-01-01
        相关资源
        最近更新 更多