【问题标题】:Dependency injection using double constructors versus single constructor that uses a DI Framework使用双构造函数的依赖注入与使用 DI 框架的单构造函数
【发布时间】:2014-01-24 02:53:04
【问题描述】:

在单元测试的上下文中,可以创建两个控制器构造函数,一个是控制器工厂默认使用的,另一个是专门用于单元测试的。

public class ProductController : Controller 
{
  private IProductRepository repository;
  public int PageSize = 10;

  // default constructor
  public ProductController() 
  {
    this.repository = new ProductRepository();
  }

  // dedicated for unit testing
  public ProductController(IProductRepository productRepository) 
  {
    this.repository = productRepository;
  }

  public ViewResult List(int page=1) 
  {
    return View(repository.Products
       .OrderBy(p => p.ProductID)
       .Skip((page - 1) * PageSize)
       .Take(PageSize));
  }
}

单元测试可以这样实现

[TestMethod]
public void Can_Paginate() 
{
  // Arrange
  Mock<IProductRepository> mock = new Mock<IProductRepository>();
  mock.Setup(m => m.Products).Returns(new Product[] 
  {
    new Product {ProductID = 1, Name = "P1"},
    new Product {ProductID = 2, Name = "P2"},
    new Product {ProductID = 3, Name = "P3"},
    new Product {ProductID = 4, Name = "P4"},
    new Product {ProductID = 5, Name = "P5"}
  }.AsQueryable());

  ProductController controller = new ProductController(mock.Object);
  controller.PageSize = 3;

  // Act
  IEnumerable<Product> result =
  (IEnumerable<Product>)controller.List(2).Model;
  // Assert
  Product[] prodArray = result.ToArray();
  Assert.IsTrue(prodArray.Length == 2);
  Assert.AreEqual(prodArray[0].Name, "P4");
  Assert.AreEqual(prodArray[1].Name, "P5");
}

在上面我能够实现单元测试。我的问题是,如果我可以使用专用构造函数实现 DI,为什么我会选择使用 DI 框架(例如 Unity、Ninject 等)?我一定在这里遗漏了一些明显的东西。

(顺便说一句,上面的代码示例大部分来自 Adam Freeman 的 Pro ASP.NET MVC 4 书,我对其进行了一些修改以适应我需要提出的问题)

【问题讨论】:

标签: c# asp.net-mvc unit-testing dependency-injection repository-pattern


【解决方案1】:

在这个简单的例子中.. 从技术上讲没有理由。

框架的重点是全局管理依赖项及其存在的各个部分......而不仅仅是注入依赖项。生命周期/范围、方式/时间、地点/原因。您在这里所拥有的仍然与 ProductRepository... 紧密耦合。

在一个复杂的应用程序中,您目前拥有的东西需要这样的东西:

this.repository = new ProductRepository(
                          new ShoppingCartRepository(
                                  new Logger()),
                          new ReviewsRepository(
                                  new Logger()),
                          new Logger());

..而使用 DI/IoC 框架,您不必担心任何布线和所有底层生命周期/连接逻辑。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多