Ska*_*osh 5 c# unit-testing moq asp.net-mvc-2
我在ASP.NET MVC应用程序中的"UserController"中有以下代码:
public class UserController : Controller
{
public ActionResult Index()
{
return RedirectToAction("List");
}
public ActionResult List()
{
IUserRepository repo = new UserRepository();
IQueryable<Business.Entities.User> users = repo.GetAll();
return View("List", users);
}
}
Run Code Online (Sandbox Code Playgroud)
使用Moq,我想模拟数据库调用"repo.GetAll()".这是我测试的内容:
[Test]
public void List()
{
Mock<IUserRepository> mockRepo = new Mock<IUserRepository>();
mockRepo.Setup(ur => ur.GetAll()).Returns(MockedGetAll());
var v = mockRepo.Object.GetAll();
var controller = new UserController();
var result = controller.List() as ViewResult;
var model = result.ViewData.Model as IQueryable<User>;
Assert.AreEqual("List", result.ViewName);
Assert.IsNotNull(model);
Assert.Greater(model.Count(), 0);
}
Run Code Online (Sandbox Code Playgroud)
我还有一个函数可以返回一些静态数据来满足测试:
private IQueryable<User> MockedGetAll()
{
List<User> users = new List<User>();
users.Add(new User(1, "mark.paterson", "mark.paterson@yahoo.com", "Mark", "Paterson", false, true));
users.Add(new User(2, "nikki.paterson", "nikki.paterson@yahoo.com", "Nikki", "Paterson", false, true));
return users.AsQueryable();
}
Run Code Online (Sandbox Code Playgroud)
测试在"Assert.Greater"中断.我得到0记录而不是2.当我调试代码时,代码实际上返回数据库调用的结果,该结果应该是0记录,而不是模拟数据.
Dar*_*rov 15
以下几行是杀死所有内容并在控制器和数据访问层之间隔离强耦合引入一个不可能的单元测试:
IUserRepository repo = new UserRepository();
Run Code Online (Sandbox Code Playgroud)
绝对不要在任何应用程序中编写任何类似的东西(不仅仅是ASP.NET MVC).无论你做什么,如果你编写这样的代码,它将总是在你的单元测试中破坏,你将无法测试它.
这是模拟/单元测试不可能的.
您应该使用构造函数注入来削弱图层之间的耦合:
public class UserController : Controller
{
private readonly IUserRepository _repo;
public UserController(IUserRepository repo)
{
_repo = repo;
}
public ActionResult Index()
{
return RedirectToAction("List");
}
public ActionResult List()
{
IQueryable<Business.Entities.User> users = _repo.GetAll();
return View("List", users);
}
}
Run Code Online (Sandbox Code Playgroud)
现在你可以通过模拟来单独进行单元测试:
[Test]
public void List()
{
Mock<IUserRepository> mockRepo = new Mock<IUserRepository>();
mockRepo.Setup(ur => ur.GetAll()).Returns(MockedGetAll());
var v = mockRepo.Object.GetAll();
var controller = new UserController(mockRepo.Object);
var result = controller.List() as ViewResult;
var model = result.ViewData.Model as IQueryable<User>;
Assert.AreEqual("List", result.ViewName);
Assert.IsNotNull(model);
Assert.Greater(model.Count(), 0);
}
Run Code Online (Sandbox Code Playgroud)
显然,因为现在您的控制器依赖于此存储库,您可以使用DI框架来配置您的依赖项.
不想使用DI框架的人经常编写这样的代码并提供2个构造函数(一个用于单元测试,一个用于实际应用程序):
private readonly IUserRepository _repo;
public UserController(IUserRepository repo)
{
_repo = repo;
}
public UserController(): this(new UserRepository())
{
}
Run Code Online (Sandbox Code Playgroud)
我提供这个是为了说明你绝对不应该做的另一件事,并强调这是穷人的DI这一事实.
| 归档时间: |
|
| 查看次数: |
2543 次 |
| 最近记录: |