【发布时间】:2016-01-30 19:39:52
【问题描述】:
因此,为了对我们的控制器进行单元测试,我正在尝试精简我们的控制器并使它们更易于测试。我们使用服务/存储库模式,我们遇到的一个问题是服务层的多个实例化。控制器中的每个方法都会实例化服务层的一个新实例。为了纠正这个问题,我想在控制器的构造函数中实例化一次。
以下是我们典型的 Controller 方法的示例:
public class GroupController : ControllerBase // ControllerBase is derived from System.Web.Mvc.Controller
{
public ActionResult EditGroup(int groupId)
{
EditGroupViewModel model = new EditGroupViewModel();
using (var service = new AccountServices(this.User)) // this.User is an instance of IPrincipal Controller.User {
Group group = service.GetGroupWithRoles(groupId);
// some code to map Group to EditGroupViewModel
}
return View(model);
}
}
任何使用 AccountServices 的方法都必须实例化该类的新实例,如上所示。理想情况下,AccountServices 将在 Controller 的构造函数中被实例化一次。但是,我不确定如何做到这一点。
这是我尝试过的:
private readonly AccountServices _service;
public GroupController(IPrincipal user)
{
_service = new AccountServices(user);
}
但是,当在构造函数上放置断点时,我看到 IPrincipal 用户仍然为空。我认为我最大的障碍是 AccountServices 需要实例化 IPrincipal Controller.User 的事实。如何在构造函数中一次性实例化AccounServices,以便Controller的所有方法都可以使用该实例?
【问题讨论】:
-
可能的解决方案是使用依赖注入容器,
AutoFac行,并将你的依赖声明为像IAccountServices这样的接口。之后,您可以将其注册为单个实例。builder.Register<AccountServices>().As<IAccountServices>().SingleInstance(); -
使用支持按请求实例化的 DI 容器(可能所有广泛使用的容器都具有这种支持)可能是更好的解决方案......(不是真的回答你的问题)。
-
MVC 不知道它应该使用 IPrincipal 调用您的控制器。您应该从构造函数中的控制器上下文中获取主体。但是考虑使用 DI 容器,它会让你的生活更轻松。
-
我建议使用 Unity 而不是 AutoFac,因为 ASP.NET Core 1 内置了 Unity。
-
你会推荐什么来模拟?起订量?
标签: c# model-view-controller repository-pattern