11-3URLTestDemo实例操作完成URL单元测试

11-3URLTestDemo

1、File -> New -> Project

在左边模板中选择Visual C#里的Web,对应到的项目类型选择ASP.NET MVC3 Web Application,并给项目取名字为11-3URLTestDemo,默认的解决方案名自动为相应的11-3URLTestDemo。

2、在解决方案管理器中,鼠标右击解决方案名字Solution’ 11-3URLTestDemo’,选择Add -> New Project,如下图。

11-3URLTestDemo实例操作完成URL单元测试

打开“Add New Project”对话框后,在左边的模板选择Visual C#里的Test,对应的项目类型选择Test Project,并取名字为URLTestDemo.UnitTests,如下图。

11-3URLTestDemo实例操作完成URL单元测试

创建好项目后,可以将不用的Class1.cs文件和URLTestDemo.UnitTests项目中的UnitTest1.cs文件删除掉。

3、给URLTestDemo.UnitTests项目添加Moq程序包和对项目11-3URLTestDemo的依赖。

在URLTestDemo.UnitTests项目名上右击鼠标,选择Manage NuGet Packages…,在打开的对话框中在线搜索Moq,并安装。再次在URLTestDemo.UnitTests项目名上右击鼠标,选择Add Reference,在打开的对话框中选择对项目11-3URLTestDemo的依赖。

4、本例是为了对URL做单元测试,在11-3URLTestDemo项目中,打开Global.asax.cs文件,将RegisterRoutes函数修改如下:

public static void RegisterRoutes(RouteCollection routes)
{
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
      routes.MapRoute("MyRoute", "{controller}/{action}");

 }

然后再在RegisterRoutes函数上点鼠标右键,选择Create Unit Tests,创建单元测试的文件,这里就会在项目URLTestDemo.UnitTests中产生一个名字为MvcApplicationTest.cs的文件,打开该文件,将MvcApplicationTest类中的原有内容删除,修改如下:

namespace URLTestDemo.UnitTests
{
    [TestClass()]
    public class MvcApplicationTest
    {
        private HttpContextBase CreateHttpContext(string targetUrl=null,
                                                    string httpMethod = "GET")
        {
            Mock<HttpRequestBase> mockRequest = new Mock<HttpRequestBase>();
            mockRequest.Setup(m => m.AppRelativeCurrentExecutionFilePath).Returns(targetUrl);
            mockRequest.Setup(m => m.HttpMethod).Returns(httpMethod);

            Mock<HttpResponseBase> mockResponse = new Mock<HttpResponseBase>();
            mockResponse.Setup(m => m.ApplyAppPathModifier(
                It.IsAny<string>())).Returns<string>(s => s);

            Mock<HttpContextBase> mockContext = new Mock<HttpContextBase>();
            mockContext.Setup(m => m.Request).Returns(mockRequest.Object);
            mockContext.Setup(m => m.Response).Returns(mockResponse.Object);

            return mockContext.Object;
        }

        private void TestRouteMatch(string url, string controller, 
            string action, object routeProperties = null,
            string httpMethod = "GET")
        {
            //布置
            RouteCollection routes = new RouteCollection();
            MvcApplication.RegisterRoutes(routes);

            //动作
            RouteData result = routes.GetRouteData(CreateHttpContext(url, httpMethod));

            //断言
            Assert.IsNotNull(result);
            Assert.IsTrue(TestIncomingRouteResult(result, controller, action, routeProperties));
        }

        private bool TestIncomingRouteResult(RouteData routeResult,
            string controller, string action, object propertySet = null)
        {
            Func<object, object, bool> valCompare = (v1, v2) =>
            {
                return StringComparer.InvariantCultureIgnoreCase.Compare(v1, v2) == 0;
            };
            bool result = valCompare(routeResult.Values["controller"], controller)
                && valCompare(routeResult.Values["action"], action);

            if (propertySet != null)
            {
                PropertyInfo[] propInfo = propertySet.GetType().GetProperties();
                foreach (PropertyInfo pi in propInfo)
                {
                    if (!(routeResult.Values.ContainsKey(pi.Name) &&
                        valCompare(routeResult.Values[pi.Name], pi.GetValue(propertySet, null))))
                    {
                        result = false;
                        break;
                    }
                }
            }
            return result;
        }

        private void TestRouteFail(string url)
        {
            //布置
            RouteCollection routes = new RouteCollection();
            MvcApplication.RegisterRoutes(routes);

            //动作
            RouteData result = routes.GetRouteData(CreateHttpContext(url));

            //断言
            Assert.IsTrue(result == null || result.Route == null);
        }

        [TestMethod]
        public void TestIncomingRoutes()
        {
            TestRouteMatch("~/Admin/Index", "Admin", "Index");
            TestRouteMatch("~/One/Two", "One", "Two");

            TestRouteFail("~/Admin/Index/Segment");
            TestRouteFail("~/Admin");
        }
    }
}

5、接下来,在菜单上选择Test -> Run -> All Tests in Solution,执行单元测试。

-lyj