zoukankan      html  css  js  c++  java
  • 模拟HttpContext单元测试

    众所周知 ASP.NET MVC 的一个显著优势即可以很方便的实现单元测试,但在我们测试过程中经常要用到HttpContext,而默认情况下单元测试框架是不提供HttpContext的模拟的,本文通过HttpContext的模拟从而实现更便利的单元测试。 

    一、Moq框架使用

    Moq是一个非常优秀的模拟框架,可以实现对接口成员的模拟,常用在TDD中。

    先来看一个简单的moq应用

    1. 定义一个简单接口且不需要实现接口(Moq就是模拟框架因此不需要实现)

    View Code

     

     1 using System;

     2 using System.Collections.Generic;

     3 using System.Linq;

     4 using System.Text;

     5

     6 namespace Stphen.Sample.ASPNETMvc.MockUnitTest.Bussiness

     7 {

     8    public interface IFoo

     9    {

    10        void DoSomeThing(string thingName);

    11        bool IsLoveFoo();

    13        string FooName { get; set; }

    14    }

    15 }

     

    2. 在测试代码中我实现了对接口的Mock

    View Code

     

    using System;

    using System.Text;

    using System.Collections.Generic;

    using System.Linq;

    using Microsoft.VisualStudio.TestTools.UnitTesting;

    using Moq;

    using Stphen.Sample.ASPNETMvc.MockUnitTest.Bussiness;

     

    namespace Stephen.Sample.ASPNETMvc.MockUnitTest.TestProject

    {

        [TestClass]

        public class MockUnitTest

        {

            private readonly Mock<IFoo> _fooMock;

     

            public MockUnitTest()

            {

                _fooMock = new Mock<IFoo>();

            }

     

            [TestMethod]

            public void MockDoSomeThingMethodTest()

            {

                _fooMock.Setup(foo => foo.DoSomeThing(It.IsAny<string>())).Callback((string s) => Console.WriteLine(s));

                _fooMock.Object.DoSomeThing("HelloWorld");

            }

     

            [TestMethod]

            public  void MockIsLoveMockFramewrokMethodTest()

            {

                _fooMock.Setup(foo => foo.IsLoveFoo()).Returns(true);

                Assert.AreEqual(true, _fooMock.Object.IsLoveFoo());

            }

            http://jiazu.wan128.cn

            [TestMethod]

            public  void MockFooNamePropertyTest()

            {

                _fooMock.Setup(foo => foo.FooName).Returns("stephen");

                Assert.AreEqual("stephen",_fooMock.Object.FooName);

            }

        }

    }

     

    第一个方法没有返回值,第二个有返回值分别用Mock 的 Callback 和 return 方法。

    二、通过Moq框架实现HttpContext的模拟(MvcContextMock)

     

      1 using System;

      2 using System.Collections.Generic;

      3 using System.Linq;

      4 using System.Text;

      5 using System.Web;

      6 using System.Web.Routing;

      7 using System.Web.Mvc;

      8 using Moq;

      9 namespace MvcContextMock

     10 {

     11     /// <summary>

     12     /// Mvc Context 工厂

     13     /// </summary>

     14     public static class MvcContextMockFactory

     15     {

     16         private static ControllerContext controllerContext = null;

     17         /// <summary>

     18         /// 创建ControllerContext

     19         /// </summary>

     20         /// <param name="controller">Controller</param>

     21         /// <returns></returns>

     22         public static ControllerContext CreateControllerContext(Controller controller)

     23         {

     24              controllerContext = new ControllerContext

     25                (

     26               CreateHttpContext(),

     27               new RouteData(),

     28                controller);

     29             return controllerContext;

     30         }

     31

     32         /// <summary>

     33         /// 创建ControllerContext

     34         /// </summary>

     35         /// <param name="controller">Controller</param>

     36         /// <param name="contextBase">httpContextBase</param>

     37         /// <returns></returns>

     38         public static ControllerContext CreateControllerContext(Controller controller, HttpContextBase contextBase)

     39         {

     40              controllerContext = new ControllerContext

     41                (

     42               contextBase,

     43               new RouteData(),

     44                controller);

     45             return controllerContext;

     46         }

     47

     48

     49         /// <summary>

     50         /// 创建ControllerContext

     51         /// </summary>

     52         /// <param name="controller">controller</param>

     53         /// <param name="url">访问的url地址</param>

     54         /// <param name="httpMethod">访问的方法(get,post)</param>

     55         /// <param name="name">路由名称</param>

     56         /// <param name="pattern">路由格式</param>

     57         /// <param name="obj">路由默认值</param>

     58         /// <returns></returns>

     59         public static ControllerContext CreateControllerContext(Controller controller, string url, string httpMethod, string name, string pattern, string obj)

     60         {

     61              controllerContext = new ControllerContext

     62                 (

     63                 CreateHttpContext(),

     64                 GetRouteData(url, httpMethod, name, pattern, obj),

     65                 controller);

     66             return controllerContext;

     67         }

     68

     69         /// <summary>

     70         /// 创建ControllerContext

     71         /// </summary>

     72         /// <param name="controller">controller</param>

     73         /// <param name="contextBase">HttpContextBase</param>

     74         /// <param name="url">访问的url地址</param>

     75         /// <param name="httpMethod">访问的方法(get,post)</param>

     76         /// <param name="name">路由名称</param>

     77         /// <param name="pattern">路由格式</param>

     78         /// <param name="obj">路由默认值</param>

     79         /// <returns></returns>

     80         public static ControllerContext CreateControllerContext(Controller controller, HttpContextBase contextBase, string url, string httpMethod, string name, string pattern, string obj)

     81         {

     82              controllerContext = new ControllerContext

     83                 (

     84                 contextBase,

     85                 GetRouteData(url, httpMethod, name, pattern, obj),

     86                 controller);

     87             return controllerContext;

     88         }

     89

     90         /// <summary>

     91         /// 创建HttpContextBase

     92         /// </summary>

     93         /// <returns></returns>

     94         public static HttpContextBase CreateHttpContext()

     95         {

     96             var context = new Mock<HttpContextBase>();

     97             var request = new Mock<HttpRequestBase>();

     98             var response = new Mock<HttpResponseBase>();

     99             var session = new Mock<HttpSessionStateBase>();

    100             var server = new Mock<HttpServerUtilityBase>();

    101             response

    102                 .Setup(rsp => rsp.ApplyAppPathModifier(Moq.It.IsAny<string>()))

    103                 .Returns((string s) => s);

    104

    105             context.Setup(ctx => ctx.Request).Returns(request.Object);

    106             context.Setup(ctx => ctx.Response).Returns(response.Object);

    107             context.Setup(ctx => ctx.Session).Returns(session.Object);

    108             context.Setup(ctx => ctx.Server).Returns(server.Object);

    109

    110             return context.Object;

    111         }

    112

    113         #region Private Method

    114         private static HttpContextBase CreateHttpContext(string url, string httpMethod)

    115         {

    116             var context = new Mock<HttpContextBase>();

    117             var request = new Mock<HttpRequestBase>();

    118             var response = new Mock<HttpResponseBase>();

    119             var session = new Mock<HttpSessionStateBase>();

    120             var server = new Mock<HttpServerUtilityBase>();

    121             response

    122                 .Setup(rsp => rsp.ApplyAppPathModifier(Moq.It.IsAny<string>()))

    123                 .Returns((string s) => s);

    124

    125             request.Setup(req => req.AppRelativeCurrentExecutionFilePath).Returns(url);

    126             request.Setup(req => req.HttpMethod).Returns(httpMethod);

    127

    128             context.Setup(ctx => ctx.Request).Returns(request.Object);

    129             context.Setup(ctx => ctx.Response).Returns(response.Object);

    130             context.Setup(ctx => ctx.Session).Returns(session.Object);

    131             context.Setup(ctx => ctx.Server).Returns(server.Object);

    132

    133             return context.Object;

    134         }

    135

    136         private static RouteData GetRouteData(string url, string httpMethod, string name, string pattern, string obj)

    137         {

    138             RouteTable.Routes.MapRoute(name, pattern, obj);

    139             var routeData =

    140                 RouteTable.Routes.

    141                 GetRouteData(CreateHttpContext(url, httpMethod));

    142             return routeData;

    143         }

    144         #endregion

    145

    146     }

    147 }

     

     


    三、在mvc中使用MockHttpContextFactory

     通过之前编写MvcContextMockFactory类我们在MVC单元测试中可以轻松的实现对HttpContext的模拟

    首先创建一个控制器

    View Code

     

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Web.Mvc;

    namespace Stephen.Sample.ASPNETMvc.MockUnitTest.Controller

    {

       public class HomeController:System.Web.Mvc.Controller

        {

          public ViewResult Index()

          {

              ViewData["controller"] = RouteData.Values["controller"];

              ViewData["action"] = RouteData.Values["action"];

              return View("Index");

          }

        }

    }

     

    因为控制器中需要获取RouteData,RouteData来自于Controller下的ControllerContext

    单元测试中调用MockHttpContextFactory模拟ControllerContext,完成单元测试。

    View Code

     

    using System;

    using System.Text;

    using System.Collections.Generic;

    using System.Linq;

    using System.Web.Mvc;

    using Microsoft.VisualStudio.TestTools.UnitTesting;

    using MvcContextMock;

    using Stephen.Sample.ASPNETMvc.MockUnitTest.Controller;

     

    namespace Stephen.Sample.ASPNETMvc.MockUnitTest.TestProject

    {

        [TestClass]

        public class HomeControllerUnitTest

        {

            [TestMethod]

            public void IndexActionTest()

            {

                var homeController = new HomeController();

                homeController.ControllerContext = MvcContextMock.MvcContextMockFactory.CreateControllerContext(homeController, "~/Home/Index", "get", "DefaultRoute", "{controller}/{action}", null);

                ViewResult result= homeController.Index();

                Assert.AreEqual("Index",result.ViewName);

                Assert.AreEqual("Home",result.ViewData["controller"]);

                Assert.AreEqual("Index", result.ViewData["action"]);

            }

        }

    }

     

    对于更简单的HttpContext在MockHttpContextFactory中有专用的方法生成与ControllerContext原理类似。

  • 相关阅读:
    java基础篇2之枚举
    java基础篇1之可变参数,增强for循环,自动装箱
    计算机常用英语
    ThreadLocal
    Tomcat 配置连接池
    数据库连接池
    装饰者模式
    JavaWeb 之事务
    MySql 批处理
    如何将大数据保存到 MySql 数据库
  • 原文地址:https://www.cnblogs.com/huangf714/p/5876069.html
Copyright © 2011-2022 走看看