gpt4 book ai didi

c# - 无法使用 Moq 在 ASP.NET MVC Controller 中模拟方法调用

转载 作者:太空狗 更新时间:2023-10-29 22:12:48 26 4
gpt4 key购买 nike

我的 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);
}
}

使用 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);
}

我还有一个函数会返回一些静态数据以满足测试:

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();
}

测试在“Assert.Greater”处中断。我得到 0 条记录而不是 2 条记录。当我调试代码时,代码实际上返回了数据库调用的结果,它应该是 0 条记录,而不是模拟数据。

最佳答案

下面这行代码杀死了一切,并在你的 Controller 和数据访问层之间引入了一个不可能隔离的单元测试强耦合:

IUserRepository repo = new UserRepository();

绝对不要在任何应用程序(不仅仅是 ASP.NET MVC)中写这样的东西。如果您编写这样的代码,无论您做什么,它总是会破坏您的单元测试,您将无法对其进行测试。

这是不可能进行模拟/单元测试的。

您应该使用构造函数注入(inject)来削弱层之间的耦合:

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);
}
}

现在您可以通过模拟进行孤立的单元测试:

[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);
}

显然,因为现在您的 Controller 依赖于此存储库,您可以使用 DI 框架来配置依赖项。

不想使用 DI 框架的人通常会这样写代码并提供 2 个构造函数(一个用于单元测试,一个用于实际应用):

private readonly IUserRepository _repo;
public UserController(IUserRepository repo)
{
_repo = repo;
}

public UserController(): this(new UserRepository())
{

}

我提供这个是为了说明另一件你绝对不应该做的事情,并强调这是 poor man's DI .

Haacked还在 his blog post 中讨论了这些问题.

关于c# - 无法使用 Moq 在 ASP.NET MVC Controller 中模拟方法调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6616345/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com