在没有命中数据库的情况下测试ASP.NET MVC控制器的干净方法?

sen*_*nfo 2 asp.net-mvc unit-testing rhino-mocks mocking

我正在尝试一种清理控制器的好方法,使它们更易于测试,而不必依赖于持续的数据库连接.我认为通过使用IObjectContext抽象出我的对象上下文,我有一个不错的开始.这适用于上下文,但我的下一个问题是我有一个通用的存储库,我在整个项目中使用了许多操作方法(参见下面的代码).

除了默认构造函数之外,我的控制器还包含一个重载,它接受IObjectContext(简单依赖注入).在我的单元测试中,我可以轻松地模拟IObjectContext.我的问题是在各种动作方法中处理我的通用存储库.我可以向控制器添加一些额外的构造函数重载,但我担心这会很快变得混乱.但是,如果没有这样做,我根本无法想到一种提高可测试性的简洁方法,因此我不必依赖数据库连接.

我有一个简单的解决方案吗?

/// <summary>
/// Initializes a new instance of the HomeController class
/// </summary>
public HomeController(IObjectContext context)
{
    _context = context;
}

/// <summary>
/// GET: /home/index
/// </summary>
/// <returns>Renders the home page</returns>
public ActionResult Index()
{
    List contacts;
    HomeViewModel model;

    using (IRepository<Contact> repository = new DataRepository<Contact>(_context))
    {
        contacts = new List(repository.GetAll());
    }

    model = new HomeViewModel(contacts);

    return View(model);
}
Run Code Online (Sandbox Code Playgroud)

如果我必须采用添加额外构造函数重载的路径以适应我的顾虑,我正在考虑添加一些私有属性(这将在需要之前对存储库进行实例化)到我的控制器为每个存储库操作方法利用.例如:

private IRepository<Contact> _contactRepository;

private IRepository<Contact> ContactRepository
{
    get
    {
        return _contactRepository ?? (_contactRepository = new DataRepository<Contact>());
    }
}
Run Code Online (Sandbox Code Playgroud)

出于单元测试的目的,我可以使用构造函数重载来预初始化存储库.

你对此有何看法?我错过了一些应该很明显的清洁工具吗?

Mar*_*ann 5

首先,摆脱你当前的Bastard Injection构造函数重载.使用DI,您应该只需要一个构造函数,这就是获取所有依赖项的构造函数.(要启用ASP.NET MVC运行时以创建控制器,请实现自定义IControllerFactory.)

下一步是通过构造函数注入所有依赖项.当你认为它因为构造函数参数太多而变得混乱时,这是一个很好的迹象,表明你违反了单一责任原则.发生这种情况时,您将提取聚合服务.

冲洗并重复:)