列表1–Controllers\ForumControllerTest.cs
using System.Web.Mvc;
using LinqToSqlExtensions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MvcFakes;
using MvcForums.Controllers;
using MvcForums.Models;
namespace MvcForums.Tests.Controllers
{
[TestClass]
public class ForumControllerTest
{
private IDataContext _dataContext;
private IForumRepository _repository;
[TestInitialize]
public void Initialize()
{
//创建数据上下文和虚构的数据
_dataContext = new FakeDataContext();
_dataContext.Insert(new Message(1, null, "Robert", "Welcome to the MVC forums!", "body1"));
_dataContext.Insert(new Message(2, 1, "Stephen", "RE:Welcome to the MVC forums!", "body2"));
_dataContext.Insert(new Message(3, 2, "Robert", "RE:Welcome to the MVC forums!", "body3"));
_dataContext.Insert(new Message(4, null, "Mark", "Another message", "body4"));
_dataContext.Insert(new Message(5, 4, "Stephen", "Yet another message", "body5"));
_dataContext.Insert(new Message(6, 5, "Jane", "Yet another message", "body6"));
//创建仓库
_repository = new ForumRepository(_dataContext);
}
[TestMethod]
public void IndexReturnsMessageThreads()
{
// Arrange
var controller = new ForumController(_repository);
// Act
var result = controller.Index() as ViewResult;
// Assert
var model = result.ViewData.Model as List<Message>;
Assert.AreEqual(2, model.Count);
}
}
}
列表1中的单元测试类包含了两个方法,名字分别为Initialize()和IndexReturnsMessageThreads()。注意,Initialize()方法前面修饰有[TestInitialize]属性。这个属性能够确保在每一个单元测试之前运行Initialize()方法。
Initialize()方法用于创建一个模拟的DataContext。一些模拟的论坛消息将被添加到该模拟的DataContext中。注意,一个论坛消息拥有下列属性:
? Id
? ParentId
? Author
? Subject
? Body
注意,我们现在创建的是一个基于线程的讨论某些主题的论坛程序。其中的论坛消息都是以线程的方式加以组织的。因此,在一个线程中可能存在若干条消息。
上面的ParentId属性描述了当前消息的父级消息。如果一条消息拥有一个NULL类型的父级消息时,那么,此消息将被假定为是这个线程中的第一条消息。
因为模拟的DataContext是在Intialize()方法中建立的,所以,测试类中所有的单元测试都可以利用这个模拟的DataContext。
注意,FakeDataContext类是作为MvcFakes工程的一部分存在的,详情请参考本文所附源码。
上述虚构的DataContext将被传递到Repository类的一个实例中。MVC论坛应用程序将利用Repository模式,其目的是为了解除系统对于任何特定的数据访问技术的依赖性。
接下来请注意,IndexReturnsMessageThreads()方法负责校验Forums控制器中的Index()方法确保其返回一个消息线程的列表。这个单元测试被分成三个部分。
在Arrange部分中,将创建一个Forum控制器的实例。注意,当创建控制器时,该repository将被传递到Forum控制器的构造器。在这个单元测试中,Forum控制器将使用借助于虚拟的DataContext实例化的repository。
接下来,在Act部分中,Index()动作被调用。该Index()动作返回一个ViewResult。
最后,在Assert部分中,ViewData.Model属性被强制转换成一个消息对象的集合。如果Index()方法返回所有的线程,那么该Index()方法应该正好返回三个消息。记住,一个线程就是一个ParentId为NULL的消息。
当你第一次试图运行列表1中的单元测试时,该测试将会失败。事实上,你的应用程序甚至不会通过编译—你将得到如图3所示的错误列表窗口。