《ASP.NET MVC 4 实战》学习笔记 5:控制器(下)

三、单元测试--确保控制器按照希望执行:

单元测试是小型的脚本化测试,通常以与产品代码同样的语言来编写。它们以与系统其余部分隔离的形式来建立并演练单个组件的功能,目的是证实它能正确工作。

1.已提供的测试项目:

如果在新建项目时勾选了“创建单元测试项目”选项,Visual Studio会用Visual Studio Unit Testing Framework(Visual Studio单元测试框架)生成一个测试项目,包含HomeControllerTest类:

 1 namespace Guestbook.Tests.Controllers
 2 {
 3     [TestClass]
 4     public class HomeControllerTest
 5     {
 6         [TestMethod]
 7         public void Index()
 8         {
 9             // Arrange
10             HomeController controller = new HomeController();//实例化控制器
11
12             // Act
13             ViewResult result = controller.Index() as ViewResult;//演练动作方法
14
15             // Assert
16             Assert.IsNotNull(result);//断言结果
17         }
18
19         [TestMethod]
20         public void About()
21         {
22             // Arrange
23             HomeController controller = new HomeController();
24
25             // Act
26             ViewResult result = controller.About() as ViewResult;
27
28             // Assert
29             Assert.AreEqual("Your application description page.", result.ViewBag.Message);
30         }
31
32         [TestMethod]
33         public void Contact()
34         {
35             // Arrange
36             HomeController controller = new HomeController();
37
38             // Act
39             ViewResult result = controller.Contact() as ViewResult;
40
41             // Assert
42             Assert.IsNotNull(result);
43         }
44     }

每个测试都有三个阶段--Arrange(准备)、Act(动作)、Assert(断言)。通常将这种编写测试的模式称为“A/A/A”模式或“3A”模式。让单元测试采用这种固定的A/A/A编程模式有利于编写格式统一的测试。

2.测试GuestbookController:
在之前的代码中GuestbookController直接实例化并使用GuestbookContext对象访问数据库。这意味着如果没有建好数据库或者数据库中没有测试数据,就不能对控制器进行测试。

代替上述对GuestbookContext的直接访问,我们引入一个存储库,让它提供一个对GuestbookEntry对象执行数据访问操作的网关:

1.新增接口:

 1 namespace Guestbook.Repository
 2 {
 3     public interface IGuestbookRepository
 4     {
 5         IList<GuestbookEntry> GetMostRecentEntries();
 6         GuestbookEntry FindById(int? id);
 7         IList<CommentSummary> GetCommentSummary();
 8         void AddEntry(GuestbookEntry entry);
 9         void Edit(GuestbookEntry entry);
10         void DeleteById(int id);
11     }
12 }

2.实现接口:

 1 namespace Guestbook.Repository
 2 {
 3     public class GuestbookRepository : IGuestbookRepository
 4     {
 5         private GuestbookContext _db = new GuestbookContext();
 6         public IList<GuestbookEntry> GetMostRecentEntries()
 7         {
 8             return (from entry in _db.Entries
 9                     orderby entry.DateAdded descending
10                     select entry).Take(20).ToList();
11         }
12         public void AddEntry(GuestbookEntry entry)
13         {
14             _db.Entries.Add(entry);
15             _db.SaveChanges();
16         }
17         public GuestbookEntry FindById(int? id)
18         {
19             var entry = _db.Entries.Find(id);
20             return entry;
21         }
22         public IList<CommentSummary> GetCommentSummary()
23         {
24             var entries = from entry in _db.Entries
25                           group entry by entry.Name into groupedByName
26                           orderby groupedByName.Count() descending
27                           select new CommentSummary
28                           {
29                               NumberOfComments=groupedByName.Count(),
30                               UserName=groupedByName.Key
31                           };
32             return entries.ToList();
33
34         }
35         public void Edit(GuestbookEntry entry)
36         {
37             _db.Entry(entry).State = EntityState.Modified;
38             _db.SaveChanges();
39         }
40         public void DeleteById(int id)
41         {
42             var entry = _db.Entries.Find(id);
43             _db.Entries.Remove(entry);
44             _db.SaveChanges();
45         }
46     }
47 }

3.修改GuestbookController:

  1 namespace Guestbook.Controllers
  2 {
  3     public class GuestbookController : Controller
  4     {
  5         private IGuestbookRepository _repository;
  6
  7         public GuestbookController()
  8         {
  9             _repository = new GuestbookRepository();
 10         }
 11
 12         public GuestbookController(IGuestbookRepository repository)
 13         {
 14             _repository = repository;
 15         }
 16         public ActionResult Index()
 17         {
 18             var mostRecentEntries=_repository.GetMostRecentEntries();
 19             return View(mostRecentEntries);
 20         }
 21         public ActionResult Details(int? id)
 22         {
 23             if (id == null)
 24             {
 25                 return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
 26             }
 27             var entry = _repository.FindById(id);
 28             if (entry == null)
 29             {
 30                 return HttpNotFound();
 31             }
 32             return View(entry);
 33         }
 34         public ActionResult Create()
 35         {
 36             return View();
 37         }
 38         [HttpPost]
 39         [ValidateAntiForgeryToken]
 40         public ActionResult Create([Bind(Include="Id,Name,Message,DateAdded")] GuestbookEntry entry)
 41         {
 42             if (ModelState.IsValid)//检查验证是否成功
 43             {
 44                 _repository.AddEntry(entry);
 45                 return RedirectToAction("Index");
 46             }
 47
 48             return View(entry);//失败时重新渲染表单
 49         }
 50         public ActionResult Edit(int? id)
 51         {
 52             if (id == null)
 53             {
 54                 return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
 55             }
 56             var entry = _repository.FindById(id);
 57             if (entry == null)
 58             {
 59                 return HttpNotFound();
 60             }
 61             return View(entry);
 62         }
 63         [HttpPost]
 64         [ValidateAntiForgeryToken]
 65         public ActionResult Edit([Bind(Include="Id,Name,Message,DateAdded")] GuestbookEntry entry)
 66         {
 67             if (ModelState.IsValid)
 68             {
 69                 _repository.Edit(entry);
 70                 return RedirectToAction("Index");
 71             }
 72             return View(entry);
 73         }
 74         public ActionResult Delete(int? id)
 75         {
 76             if (id == null)
 77             {
 78                 return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
 79             }
 80             var entry = _repository.FindById(id);
 81             if (entry == null)
 82             {
 83                 return HttpNotFound();
 84             }
 85             return View(entry);
 86         }
 87         [HttpPost, ActionName("Delete")]
 88         [ValidateAntiForgeryToken]
 89         public ActionResult DeleteConfirmed(int id)
 90         {
 91             _repository.DeleteById(id);
 92             return RedirectToAction("Index");
 93         }
 94
 95         public ActionResult CommentSumary()
 96         {
 97             var entries = _repository.GetCommentSummary();
 98             return View(entries.ToList());
 99         }
100     }
101 }

4.不与数据库交互的IGuestbookRepository接口的模仿实现:

 1 namespace Guestbook.Repository
 2 {
 3     public class FakeGuestbookRepository:IGuestbookRepository
 4     {
 5         public List<GuestbookEntry> _entries = new List<GuestbookEntry>();
 6         public IList<GuestbookEntry> GetMostRecentEntries()
 7         {
 8             return new List<GuestbookEntry>
 9             {
10                 new GuestbookEntry
11                 {
12                   DateAdded=new DateTime(2014,11,13),
13                   Id=1,
14                   Message="Test Message",
15                   Name="陈家洛"
16                 }
17             };
18         }
19         public void AddEntry(GuestbookEntry entry)
20         {
21             _entries.Add(entry);
22         }
23         public GuestbookEntry FindById(int? id)
24         {
25             return _entries.SingleOrDefault(x => x.Id == id);
26         }
27         public IList<CommentSummary> GetCommentSummary()
28         {
29             return new List<CommentSummary>
30             {
31                 new CommentSummary
32                 {
33                     UserName="陈家洛",
34                     NumberOfComments=3
35                 }
36             };
37
38         }
39         public void Edit(GuestbookEntry entry)
40         {
41             //
42         }
43         public void DeleteById(int id)
44         {
45             //
46         }
47     }
48 }

5.测试Index动作:

 1 namespace Guestbook.Tests.Controllers
 2 {
 3     [TestClass]
 4     public class GuestbookControllerTest
 5     {
 6         [TestMethod]
 7         public void Index_RendersView()
 8         {
 9             var controller = new GuestbookController(new FakeGuestbookRepository());
10             var result=controller.Index() as ViewResult;
11             Assert.IsNotNull(result);
12         }
13         [TestMethod]
14         public void Index_gets_most_rencent_entries()
15         {
16             var controller = new GuestbookController(new FakeGuestbookRepository());
17             var result=(ViewResult)controller.Index();
18             var entries=(IList<GuestbookEntry>) result.Model;
19             Assert.AreEqual(1,entries.Count);
20         }
21
22     }
23 }

第一个测试调用Index动作,并简单断言它渲染一个视图;第二个断言传递给视图一个GuestbookEntry对象列表。

源码下载 密码:bwmq

时间: 2024-08-11 07:36:58

《ASP.NET MVC 4 实战》学习笔记 5:控制器(下)的相关文章

ASP.Net MVC开发基础学习笔记(3):Razor视图引擎、控制器与路由机制学习

首页 头条 文章 频道                         设计频道 Web前端 Python开发 Java技术 Android应用 iOS应用 资源 小组 相亲 频道 首页 头条 文章 小组 相亲 资源 设计 前端 Python Java 安卓 iOS 登录 注册 首页 最新文章 经典回顾 开发 Web前端 Python Android iOS Java C/C++ PHP .NET Ruby Go 设计 UI设计 网页设计 交互设计 用户体验 设计教程 设计职场 极客 IT技术

ASP.Net MVC开发基础学习笔记:三、Razor视图引擎、控制器与路由机制学习

一.天降神器“剃须刀” — Razor视图引擎 1.1 千呼万唤始出来的MVC3.0 在MVC3.0版本的时候,微软终于引入了第二种模板引擎:Razor.在这之前,我们一直在使用WebForm时代沿留下来的ASPX引擎或者第三方的NVelocity模板引擎. Razor在减少代码冗余.增强代码可读性和Visual Studio智能感知方面,都有着突出的优势.Razor一经推出就深受广大ASP.Net开发者的喜爱. 1.2 Razor的语法 (1)Razor文件类型:Razor支持两种文件类型,分

ASP.Net MVC开发基础学习笔记:二、HtmlHelper与扩展方法

一.一个功能强大的页面开发辅助类—HtmlHelper初步了解 1.1 有失必有得 在ASP.Net MVC中微软并没有提供类似服务器端控件那种开发方式,毕竟微软的MVC就是传统的请求处理响应的回归.所以抛弃之前的那种事件响应的模型,抛弃服务器端控件也理所当然. 但是,如果手写Html标签效率又比较低,可重用度比较低.这时,我们该怎样来提高效率呢?首先,经过上篇我们知道可以通过ViewData传递数据,于是我们可以写出以下的Html代码: <input name="UserName&quo

ASP.Net MVC开发基础学习笔记:一、走向MVC模式

一.ASP.Net的两种开发模式 1.1 ASP.Net WebForm的开发模式 (1)处理流程 在传统的WebForm模式下,我们请求一个例如http://www.aspnetmvc.com/blog/index.aspx的URL,那么我们的WebForm程序会到网站根目录下去寻找blog目录下的index.aspx文件,然后由index.aspx页面的CodeBehind文件(.CS文件)进行逻辑处理,其中或许也包括到数据库去取出数据(其中的经过怎样的BLL到DAL这里就不谈了),然后再由

ASP.Net MVC开发基础学习笔记(1):走向MVC模式

链接地址:http://blog.jobbole.com/84992/ 一.ASP.Net的两种开发模式 1.1 ASP.Net WebForm的开发模式 (1)处理流程 在传统的WebForm模式下,我们请求一个例如http://www.aspnetmvc.com/blog/index.aspx的URL,那么我们的WebForm程序会到网站根目录下去寻找blog目录下的index.aspx文件,然后由index.aspx页面的CodeBehind文件(.CS文件)进行逻辑处理,其中或许也包括到

ASP.NET MVC Web API 学习笔记---Web API概述及程序示例

1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过在浏览器中使用 JavaScript来创建更丰富的HTML体验.所以我相信Web API会越来越有它的用武之地. 说道Web API很多人都会想到Web服务,但是他们仍然有一定的区别:Web API服务是通过一般的 HTTP公开了,而不是通过更正式的服务合同 (如SOAP) 2. ASP.NET W

ASP.NET MVC Web API 学习笔记---第一个Web API程序

http://www.cnblogs.com/qingyuan/archive/2012/10/12/2720824.html 1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过在浏览器中使用 JavaScript来创建更丰富的HTML体验.所以我相信Web API会越来越有它的用武之地. 说道Web API很多人都会想到Web服务,但是他们仍然有

ASP.Net MVC开发基础学习笔记:四、校验、AJAX与过滤器

一.校验 — 表单不是你想提想提就能提 1.1 DataAnnotations(数据注解) 位于 System.ComponentModel.DataAnnotations 命名空间中的特性指定对数据模型中的各个字段的验证.这些特性用于定义常见的验证模式,例如范围检查和必填字段.而 DataAnnotations 特性使 MVC 能够提供客户端和服务器验证检查,使你无需进行额外的编码来控制数据的有效. 通过为模型类增加数据描述的 DataAnnotations ,我们可以容易地为应用程序增加验证

ASP.Net MVC开发基础学习笔记(5):区域、模板页与WebAPI初步

一.区域—麻雀虽小,五脏俱全的迷你MVC项目 1.1 Area的兴起 为了方便大规模网站中的管理大量文件,在ASP.NET MVC 2.0版本中引入了一个新概念—区域(Area). 在项目上右击创建新的区域,可以让我们的项目不至于太复杂而导致管理混乱.有了区域后,每个模块的页面都放入相应的区域内进行管理很方便.例如:上图中有两个模块,一个是Admin模块,另一个是Product模块,所有关于这两个模块的控制器.Model以及视图都放入各自的模块内.可以从上图中看出,区域的功能类似一个小的MVC项

【转载】ASP.NET MVC Web API 学习笔记---第一个Web API程序

1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过在浏览器中使用 JavaScript来创建更丰富的HTML体验.所以我相信Web API会越来越有它的用武之地. 说道Web API很多人都会想到Web服务,但是他们仍然有一定的区别:Web API服务是通过一般的 HTTP公开了,而不是通过更正式的服务合同 (如SOAP)  2. ASP.NET