ASP.NET MVC SportStore 购物网示例(3)

测试驱动开发(TDD)

下载工具

http://www.nunit.org

http://code.google.com/p/moq

为Tests项目添加如下引用:

nunit.Framework

System.Web

System.Web.Abstractions

System.Web.Routing

System.Web.Mvc

Moq.Dll

DomainModel

WebUI

为Tests创建类

[TestFixture]

public class ProductsControllerTests

{

[Test]

public void List_Presents_Correct_Page_Of_Products()

{

IProductsRepository repository = MockProductsRepository(

new Product { Name = "P1" }, new Product { Name = "P2" },

new Product { Name = "P3" }, new Product { Name = "P4" },

new Product { Name = "P5" }

);

ProductsController controller = new ProductsController(repository);

controller.PageSize = 3;

var result = controller.List(2);

Assert.IsNotNull(result, "Didn't render view");

var products = result.ViewData.Model as IList<Product>;

Assert.AreEqual(2, products.Count, "Got wrong number of products");

Assert.AreEqual("P4", products[0].Name);

Assert.AreEqual("P5", products[1].Name);

}

static IProductsRepository MockProductsRepository(params Product[] prods)

{

var mockProductsRepos = new Moq.Mock<IProductsRepository>();

mockProductsRepos.Setup(x => x.Products).Returns(prods.AsQueryable());

return mockProductsRepos.Object;

}

}

试着去编译代码,存在错误,因为 PageSize 和 List(2)都不存在。

clip_image002

为ProductController类添加 PageSize和带参数的List。

public int PageSize;

public ViewResult List(int page)

编译Tests项目。打开NUnit 载入生成的 Test.dll 文件,运行测试。

clip_image004

测试结果失败。

修改ProductsController类

public int PageSize = 4;

public ViewResult List(int page)

{

return View(productsRepository.Products

.Skip((page-1)*PageSize)

.Take(PageSize)

.ToList()

);

}

测试显示绿色,通过。

配置自定义的URL

为List()添加参数后,测试可能通过但运行我们实际的程序会出现错误。

clip_image006

添加自己的路由表

打开 Global.asax.cs改变代码如下:

routes.MapRoute(

null, // Route name

"", // URL with parameters

new { controller = "Products", action = "List", page = "1" } // Parameter defaults

);

routes.MapRoute(

null,

"Page{page}", //URL pattern, e.g. ~/Page377

new { controller = "Products", action = "List" },

new { Page = @"\d+" } //Constraints: page must be numerical

);

添加了两个URL映射:

一个空的URL, 通过 http://myweb/ 访问,为List传递了默认的参数 page=1。返回第一页数据。

Page{page}, http://myweb/Page123, 使用正则表达式 "\d+"来访问指定页的数据。

clip_image008

显示分页列表

创建测试类 PagingHelperTests

namespace Tests

{

using WebUI.HtmlHelpers; // The extension method will live in this namespace

[TestFixture]

public class PagingHelperTests

{

[Test]

public void PageLinks_Method_Extends_HtmlHelper()

{

HtmlHelper html = null;

html.PageLinks(0, 0, null);

}

[Test]

public void PageLinks_Producs_Anchor_Tags()

{

//第一个参数是当前页的索引

//第二个参数是每页的数量

//第三个参数是lambda方法,将一个页数映射到它的url

string links =((HtmlHelper)null).PageLinks(2,3 ,i=> "Page" + i);

Assert.AreEqual(@"<a href=""Page1"">1</a><a class=""selected"" href=""Page2"">2</a><a href=""Page3"">3</a>",links);

}

}

}

在WebUI里添加类

namespace WebUI.HtmlHelpers

{

public static class PagingHelpers

{

public static string PageLinks(this HtmlHelper html, int currentPage, int totalPages, Func<int, string> pageUrl)

{

StringBuilder result = new StringBuilder();

for (int i = 1; i <= totalPages; i++)

{

TagBuilder tag = new TagBuilder("a"); //create <a>

tag.MergeAttribute("href", pageUrl(i)); // <a href="page3" />

tag.InnerHtml = i.ToString(); //<a href="page3">3</a>

if (i == currentPage)

tag.AddCssClass("selected"); //<a href="page3" class="selected">3</a>

result.Append(tag.ToString());

}

return result.ToString();

}

}

}

测试Tests.dll看是否通过。注意 使用result.Append和result.AppendLine的区别。后者会添加 "\r\n" 格式标记。

为List.aspx添加引用

<%@ Import Namespace="WebUI.HtmlHelpers" %>

如果要为所有页都使用这个命名空间,在web.config中找到 system.web/pages添加如下代码:

<namespaces>

<add namespace="System.Web.Mvc"/>

<add namespace="System.Web.Mvc.Ajax"/>

<add namespace="WebUI.HtmlHelpers"/>

。。。。

</namespaces>

</pages>

如下代码

<%=Html.PageLinks(2,3,i=>Url.Action("List",new {page=i})) %>

将生成:

<a href="/Page1">1</a>

<a class="selected" href="/Page2">2</a>

<a href="/Page3">3</a>

为视图提供一个页数

在ProductsControllerTests.cs的 List_Presents_Correct_Page_Of_Products()中添加如下测试代码:

Assert.AreEqual(2, products.Count, "Got wrong number of products");

Assert.AreEqual(2, (int)result.ViewData["CurrentPage"], "Wrong page number");

Assert.AreEqual(2, (int)result.ViewData["TotalPages"], "Wrong page count");

Assert.AreEqual("P4", products[0].Name);

Assert.AreEqual("P5", products[1].Name);

使用ViewData来存储当前页码和总页数,为ProductsController的List()方法添加代码:

public ViewResult List(int page)

{

int numProducts = productsRepository.Products.Count();

ViewData["TotalPages"] = (int)Math.Ceiling((double)numProducts / PageSize);

ViewData["CurrentPage"] = page;

return View(productsRepository.Products

.Skip((page-1)*PageSize)

.Take(PageSize)

.ToList()

);

}

运行测试,看是否通过。

最后在List.aspx中添加分页代码:

<%=Html.PageLinks((int)ViewData["CurrentPage"],(int)ViewData["TotalPages"],i=>Url.Action("List",new {page=i})) %>

F5 运行。

clip_image010

posted @ 2011-03-24 18:46  敏捷学院  阅读(490)  评论(0编辑  收藏  举报