使用 TDD 设计 MVC 控制器进行数据库调用

Design MVC Controller using TDD for database calls

我是 MVC 和单元测试的新手。我需要对我的控制器进行单元测试,但恐怕我可能没有正确设置它们。

例如:

public class MyController
{
     public ActionResult Index(int id)
     {
         var locations = new MyLocations().GetLocations();
         //linq code here that filters based on id
         return View(filteredLocations)
     }
}

这是一个非常简单的示例,但是我该如何正确设置它以便我可以使用 TDD 模型,这样当我进行单元测试时我可以提供一个静态位置列表作为 return 值?

我不确定应该如何正确构建它。

由于 new MyLocations() 的紧密耦合意味着您将无法操纵它的行为。

创建依赖项的抽象

public interface ILocations {
    IEnumerable<Location> GetLocations();
}

让实现派生自抽象

public class MyLocations : ILocations {
    public IEnumerable<Location> GetLocations() {
        //...db calls here
    }
}

并重构控制器以依赖抽象

public class MyController : Controller {
    private readonly ILocations myLocations;

    public MyController(ILocations myLocations) {
        this.myLocations = myLocations;
    }

    public ActionResult Index(int id) {
       var locations = myLocations.GetLocations();
       //linq code here that filters based on id
       return View(filteredLocations);
    }
}

控制器现在是可测试的,因为在隔离测试时可以通过模拟框架或继承将替代品注入控制器。

在生产中,您将配置 DependencyResolver 以将接口映射到实现并将其注入控制器。

参考ASP.NET MVC 4 Dependency Injection