zoukankan      html  css  js  c++  java
  • 如何进行ASP.NET MVC 的测试

    本文参考了http://stephenwalther.com/blog/的内容。

    今天需要对ASP.NET MVC的Controller进行测试,我们都知道当我们在测试工程里new一个controller时,这个controller里的httpcontext是空的,也就是session,cookie, form等都是空。

    方法一:Mock controller的HttpContext, 暂时失败

    那么我们如何对controller进行测试呢,我首先想到的是mock一个httpcontext,这里我用的是Rhino Mocks

    public static class MvcMockHelpers

        {

            public static HttpContextBase FakeHttpContext(this MockRepository mocks)

            {

                HttpContextBase context = mocks.PartialMock<HttpContextBase>();

                HttpRequestBase request = mocks.PartialMock<HttpRequestBase>();

                HttpResponseBase response = mocks.PartialMock<HttpResponseBase>();

                HttpSessionStateBase session = mocks.PartialMock<HttpSessionStateBase>();

                HttpServerUtilityBase server = mocks.PartialMock<HttpServerUtilityBase>();

     

                SetupResult.For(context.Request).Return(request);

                SetupResult.For(context.Response).Return(response);               

                SetupResult.For(context.Session).Return(session);

                SetupResult.For(context.Server).Return(server);

     

                mocks.Replay(context);

                return context;

            }

     

            public static HttpContextBase FakeHttpContext(this MockRepository mocks, string url)

            {

                HttpContextBase context = FakeHttpContext(mocks);

                context.Request.SetupRequestUrl(url);

                return context;

            }

     

            public static void SetFakeControllerContext(this MockRepository mocks, Controller controller)

            {

                var httpContext = mocks.FakeHttpContext();

                ControllerContext context = new ControllerContext(new RequestContext(httpContext, new RouteData()), controller);

                controller.ControllerContext = context;

            }

    下面我们建立一个ASP.NET MVC工程

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Web;

    using System.Web.Mvc;

    using System.Web.Mvc.Ajax;

     

    namespace MVCTest.Controllers

    {

        [HandleError]

        public class HomeController : Controller

        {

            public ActionResult TestSession()

            {

                Session["name"] = "Jack Wang";

                ViewData["Title"] = "Home Page";

                ViewData["Message"] = "Welcome to ASP.NET MVC!";

                if (Session["CurrentCulture"] != null)

                {

                    ViewData["CurrentCulture"] = Session["CurrentCulture"];

                }

                return View();

            }

     

            public ActionResult TestForm()

            {

                ViewData["Name"] = Request.Form["Name"];

                ViewData["Age"] = Request.Form["Age"];

                ViewData["count"] = Request.Form.Count;

                return View();

            }

     

            public ActionResult TestLogin()

            {

                if (User.Identity.IsAuthenticated)

                {

                    ViewData["userName"] = User.Identity.Name;

                    return View("Admin");

                }

                else

                {

                    return RedirectToAction("Index");

                }

            }

     

            public ActionResult Admin()

            {

                if (User.IsInRole("Admin"))

                {

                    return View("Admin");

                }

                else

                {

                    return RedirectToAction("Index");

                }

            }

     

            public ViewResult Details()

            {

                ViewData["PageSize"] = Request.QueryString["PageSize"];

                ViewData["CurrentPage"] = Request.QueryString["CurrentPage"];

                ViewData["count"] = Request.QueryString.Count;

     

                return View();

            }

            public ViewResult TestCookie()

            {

                ViewData["key"] = Request.Cookies["key"].Value;

                return View();

            }

        }

    }

     

    测试代码

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Web.Mvc;

    using Microsoft.VisualStudio.TestTools.UnitTesting;

    using MVCTest;

    using MVCTest.Controllers;

    using MvcFakes;

    using System.Web.SessionState;

    using System.Web;

    using System.Collections.Specialized;

    using Rhino.Mocks;

    namespace MVCTest.Tests.Controllers

    {

        /// <summary>

        /// Summary description for HomeControllerTestByMock

        /// </summary>

        [TestClass]

        public class HomeControllerTestByMock

        {

            public HomeControllerTestByMock()

            {

                //

                // TODO: Add constructor logic here

                //

            }

            private MockRepository mocks;

            [TestInitialize]

            public void Setup()

            {

                mocks = new MockRepository();

            }

            [TestMethod]

            public void TestSession()

            {

                // Arrange

     

                HomeController controller = new HomeController();

                mocks.SetFakeControllerContext(controller);

                controller.Session.Add("name", "Jack Wang");

                SetupResult.For(controller.Session["CurrentCulture"]).Return("zh-CN");

     

                mocks.ReplayAll();

                // Act

                ViewResult result = controller.TestSession() as ViewResult;

     

                // Assert

                ViewDataDictionary viewData = result.ViewData;

                Assert.AreEqual("Home Page", viewData["Title"]);

                Assert.AreEqual("Welcome to ASP.NET MVC!", viewData["Message"]);

                Assert.AreEqual(controller.Session["name"], "Jack Wang");

                Assert.AreEqual("zh-CN", viewData["CurrentCulture"]);

            }

     

        }

    }

    运行,测试

    image

    从错误信息可以看到是因为代码里Session["name"] = "Jack Wang"出错

    本人排查很久,只知道mock的controllercontext的Session里没有这个Key,但现在还没有找到如何解决,哪位高人能帮吗解决?

     

    二,自己写个模拟的Fake类,测试通过

     

    既然这种方法不行,我们只能换一种方法,还好controller的ControllerContext可以赋值,这样我们就通过继承ControllerContext来Fake

    using System;

    using System.Collections;

    using System.Collections.Generic;

    using System.Collections.Specialized;

    using System.Linq;

    using System.Text;

    using System.Web;

    using System.Web.SessionState;

     

    namespace MvcFakes

    {

        public class FakeHttpSessionState : HttpSessionStateBase

        {

            private readonly SessionStateItemCollection _sessionItems;

     

            public FakeHttpSessionState(SessionStateItemCollection sessionItems)

            {

                _sessionItems = sessionItems;

            }

     

            public override void Add(string name, object value)

            {

                _sessionItems[name] = value;

            }

     

            public override int Count

            {

                get

                {

                    return _sessionItems.Count;

                }

            }

     

            public override IEnumerator GetEnumerator()

            {

                return _sessionItems.GetEnumerator();

            }

     

            public override NameObjectCollectionBase.KeysCollection Keys

            {

                get

                {

                    return _sessionItems.Keys;

                }

            }

     

            public override object this[string name]

            {

                get

                {

                    return _sessionItems[name];

                }

                set

                {

                    _sessionItems[name] = value;

                }

            }

     

            public override object this[int index]

            {

                get

                {

                    return _sessionItems[index];

                }

                set

                {

                    _sessionItems[index] = value;

                }

            }

     

            public override void Remove(string name)

            {

                _sessionItems.Remove(name);

            }

        }

    }

     

    using System;

    using System.Collections.Specialized;

    using System.Web;

     

    namespace MvcFakes

    {

     

        public class FakeHttpRequest : HttpRequestBase

        {

            private readonly NameValueCollection _formParams;

            private readonly NameValueCollection _queryStringParams;

            private readonly HttpCookieCollection _cookies;

     

            public FakeHttpRequest(NameValueCollection formParams, NameValueCollection queryStringParams, HttpCookieCollection cookies)

            {

                _formParams = formParams;

                _queryStringParams = queryStringParams;

                _cookies = cookies;

            }

     

            public override NameValueCollection Form

            {

                get

                {

                    return _formParams;

                }

            }

     

            public override NameValueCollection QueryString

            {

                get

                {

                    return _queryStringParams;

                }

            }

     

            public override HttpCookieCollection Cookies

            {

                get

                {

                    return _cookies;

                }

            }

     

        }

    }

     

    using System;

    using System.Security.Principal;

     

    namespace MvcFakes

    {

     

     

        public class FakeIdentity : IIdentity

        {

            private readonly string _name;

     

            public FakeIdentity(string userName)

            {

                _name = userName;

     

            }

     

            public string AuthenticationType

            {

                get { throw new System.NotImplementedException(); }

            }

     

            public bool IsAuthenticated

            {

                get { return !String.IsNullOrEmpty(_name); }

            }

     

            public string Name

            {

                get { return _name; }

            }

     

        }

     

     

    }

     

    using System;

    using System.Linq;

    using System.Security.Principal;

     

    namespace MvcFakes

    {

     

        public class FakePrincipal : IPrincipal

        {

            private readonly IIdentity _identity;

            private readonly string[] _roles;

     

            public FakePrincipal(IIdentity identity, string[] roles)

            {

                _identity = identity;

                _roles = roles;

            }

     

            public IIdentity Identity

            {

                get { return _identity; }

            }

     

            public bool IsInRole(string role)

            {

                if (_roles == null)

                    return false;

                return _roles.Contains(role);

            }

        }

    }

     

    using System;

    using System.Collections.Specialized;

    using System.Security.Principal;

    using System.Web;

    using System.Web.SessionState;

     

    namespace MvcFakes

    {

        public class FakeHttpContext : HttpContextBase

        {

            private readonly FakePrincipal _principal;

            private readonly NameValueCollection _formParams;

            private readonly NameValueCollection _queryStringParams;

            private readonly HttpCookieCollection _cookies;

            private readonly SessionStateItemCollection _sessionItems;

     

            public FakeHttpContext(FakePrincipal principal, NameValueCollection formParams, NameValueCollection queryStringParams, HttpCookieCollection cookies, SessionStateItemCollection sessionItems )

            {

                _principal = principal;

                _formParams = formParams;

                _queryStringParams = queryStringParams;

                _cookies = cookies;

                _sessionItems = sessionItems;

            }

     

            public override HttpRequestBase Request

            {

                get

                {

                    return new FakeHttpRequest(_formParams, _queryStringParams, _cookies);

                }

            }

     

            public override IPrincipal User

            {

                get

                {

                    return _principal;

                }

                set

                {

                    throw new System.NotImplementedException();

                }

            }

     

            public override HttpSessionStateBase Session

            {

                get

                {

                    return new FakeHttpSessionState(_sessionItems);

                }

            }

     

        }

    }

     

    using System;

    using System.Collections.Specialized;

    using System.Web;

    using System.Web.Mvc;

    using System.Web.Routing;

    using System.Web.SessionState;

     

    namespace MvcFakes

    {

     

        public class FakeControllerContext : ControllerContext

        {

            public FakeControllerContext(ControllerBase controller)

                : this(controller, null, null, null, null, null, null)

            {

            }

     

            public FakeControllerContext(ControllerBase controller, HttpCookieCollection cookies)

                : this(controller, null, null, null, null, cookies, null)

            {

            }

     

            public FakeControllerContext(ControllerBase controller, SessionStateItemCollection sessionItems)

                : this(controller, null, null, null, null, null, sessionItems)

            {

            }

     

     

            public FakeControllerContext(ControllerBase controller, NameValueCollection formParams)

                : this(controller, null, null, formParams, null, null, null)

            {

            }

     

     

            public FakeControllerContext(ControllerBase controller, NameValueCollection formParams, NameValueCollection queryStringParams)

                : this(controller, null, null, formParams, queryStringParams, null, null)

            {

            }

     

     

     

            public FakeControllerContext(ControllerBase controller, string userName)

                : this(controller, userName, null, null, null, null, null)

            {

            }

     

     

            public FakeControllerContext(ControllerBase controller, string userName, string[] roles)

                : this(controller, userName, roles, null, null, null, null)

            {

            }

     

     

            public FakeControllerContext

                (

                    ControllerBase controller,

                    string userName,

                    string[] roles,

                    NameValueCollection formParams,

                    NameValueCollection queryStringParams,

                    HttpCookieCollection cookies,

                    SessionStateItemCollection sessionItems

                )

                : base(new FakeHttpContext(new FakePrincipal(new FakeIdentity(userName), roles), formParams, queryStringParams, cookies, sessionItems),

                new RouteData(), controller)

            { }

        }

    }

     

    下面是测试类

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Web.Mvc;

    using Microsoft.VisualStudio.TestTools.UnitTesting;

    using MVCTest;

    using MVCTest.Controllers;

    using MvcFakes;

    using System.Web.SessionState;

    using System.Web;

    using System.Collections.Specialized;

    namespace MVCTest.Tests.Controllers

    {

        /// <summary>

        /// Summary description for HomeControllerTest

        /// </summary>

        [TestClass]

        public class HomeControllerTest

        {

            [TestMethod]

            public void TestSession()

            {

                // Arrange

                HomeController controller = new HomeController();

                var sessionItems = new SessionStateItemCollection();

                sessionItems["CurrentCulture"] = "zh-CN";

                controller.ControllerContext = new FakeControllerContext(controller, sessionItems);

                // Act

                ViewResult result = controller.TestSession() as ViewResult;

     

                // Assert

                ViewDataDictionary viewData = result.ViewData;

                Assert.AreEqual("Home Page", viewData["Title"]);

                Assert.AreEqual("Welcome to ASP.NET MVC!", viewData["Message"]);

                Assert.AreEqual(sessionItems["name"], "Jack Wang");

                Assert.AreEqual("zh-CN", viewData["CurrentCulture"]);

            }

            [TestMethod]

            public void TestFakeFormParams()

            {

     

                var controller = new HomeController();

     

                var formParams = new NameValueCollection { { "Name", "Jack" }, { "Age", "28" } };

                controller.ControllerContext = new FakeControllerContext(controller, formParams);

     

                var result = controller.TestForm() as ViewResult;

                Assert.AreEqual("Jack", result.ViewData["Name"]);

                Assert.AreEqual("28", result.ViewData["Age"]);

                Assert.AreEqual(formParams.Count, result.ViewData["count"]);

            }

     

            [TestMethod]

            public void TestFakeQueryStringParams()

            {

                var controller = new HomeController();

     

                var queryStringParams = new NameValueCollection { { "PageSize", "10" }, { "CurrentPage", "5" } };

                controller.ControllerContext = new FakeControllerContext(controller, null, queryStringParams);

     

                var result = controller.Details() as ViewResult;

                Assert.AreEqual("10", result.ViewData["PageSize"]);

                Assert.AreEqual("5", result.ViewData["CurrentPage"]);

                Assert.AreEqual(queryStringParams.Count, result.ViewData["count"]);

            }

     

            [TestMethod]

            public void TestFakeUser()

            {

                var controller = new HomeController();

     

                controller.ControllerContext = new FakeControllerContext(controller, "Jack Wang");

                var result = controller.TestLogin() as ActionResult;

                Assert.IsInstanceOfType(result, typeof(ViewResult));

                ViewDataDictionary viewData = ((ViewResult)result).ViewData;

                Assert.AreEqual("Jack Wang", viewData["userName"]);

     

     

                controller.ControllerContext = new FakeControllerContext(controller);

                result = controller.TestLogin() as ActionResult;

                Assert.IsInstanceOfType(result, typeof(RedirectToRouteResult));

            }

     

     

            [TestMethod]

            public void TestFakeUserRoles()

            {

     

                var controller = new HomeController();

     

     

                controller.ControllerContext = new FakeControllerContext(controller, "Jack Wang", new string[] { "Admin" });

                var result = controller.Admin() as ActionResult;

                Assert.IsInstanceOfType(result, typeof(ViewResult));

     

     

                controller.ControllerContext = new FakeControllerContext(controller);

                result = controller.Admin() as ActionResult;

                Assert.IsInstanceOfType(result, typeof(RedirectToRouteResult));

            }

     

     

     

            [TestMethod]

            public void TestCookies()

            {

     

                var controller = new HomeController();

     

     

                var cookies = new HttpCookieCollection();

                cookies.Add(new HttpCookie("key", "a"));

                controller.ControllerContext = new FakeControllerContext(controller, cookies);

                var result = controller.TestCookie() as ViewResult;

     

     

                Assert.AreEqual("a", result.ViewData["key"]);

            }

        }

    }

    测试完全通过

    image 

     

    总结: 个人感觉ASP.NET MVC的测试是很不友好的,和ruby on rails相比,在测试这一块还有很大的距离,希望正式版里这一块能够加强

     

    王德水 写于2008-01-05 00:30分

     

    本文源码下载

  • 相关阅读:
    GC 的认识
    SSRF 攻击技术
    文件包含漏洞
    文件的上传和下载
    XSS
    SQL注入工具 sqlmap
    自动化测试框架
    mac配置环境变量
    pycharm与git想集成 上传下载代码
    测试人员需要掌握的linux基本操作
  • 原文地址:https://www.cnblogs.com/cnblogsfans/p/1368630.html
Copyright © 2011-2022 走看看