如何在进行单元测试时将多个依赖项对象传递给控制器​​构造函数?

时间:2014-04-09 12:02:32

标签: c# unit-testing dependency-injection moq

我有一个控制器,其中有多个依赖项。我为该控制器创建了一个参数构造函数,该控制器采用了一个主要依赖项(服务层)的对象。

 public class ProductController 
 {

       private IProductService _productService ;
       public ProductController(IProductService productService)
       {
           this._productService = productService;
       }
  }

但是在控制器中有一些方法可以处理多个依赖项。

   Public ActionResult GetProductDetails()
   {
        List<CategoryDto> catList = CategoryService.GetAllCategories()).ToList();

        ProductViewModel model = new ProductViewModel
        {
           Name="",
           Categories = catList
       };
       //other stuffs...

   }
  
    

在上面的方法中有一个不同的依赖CategoryService.And我想要模拟我需要创建不同的构造函数的依赖项,还是我可以将多个依赖项对象传递给相同的构造函数?

  

2 个答案:

答案 0 :(得分:2)

将所有依赖项注入您正在测试的类(SUT)。您可以使用构造函数或属性注入。我会选择构造函数注入:

 public class ProductController 
 {
       private IProductService productService;
       private ICategoryService categoryService;

       public ProductController(IProductService productService, 
                                ICategoryService categoryService)
       {
           this.productService = productService;
           this.categoryService = categoryService;
       }

       public ActionResult GetProductDetails()
       {
           var categories = categoryService.GetAllCategories().ToList();
           // ...
       }
  }

在测试中,您可以使用setup方法(NUnit语法)创建模拟依赖项并将其传递给SUT:

  private ProductController controller;
  private Mock<IProductService> productServiceMock;
  private Mock<ICategoryService> categoryServiceMock;


  [SetUp]
  public void Setup()
  {
      productServiceMock = new Mock<IProductService>();
      categoryServiceMock = new Mock<ICategoryService>();
      controller = new ProductController(productServiceMock.Object,
                                         categoryServiceMock.Object);
  }

然后你可以在练习SUT之前安排测试方法中的任何这个模拟对象:

  [Test]
  public void ShouldReturnProductDetails()
  {
      List<CategoryDto> categories = // ...
      categoryServiceMock.Setup(cs => cs.GetAllCategories()).Returns(categories);

      var result = controller.GetProductDetails();
      // Assert
  }

答案 1 :(得分:0)

使用服务定位模式:控制器使用服务定位器来获取服务实例。

在构造函数中:

public class ProductController 
 {
       private IServiceLocator _serviceLocator;


       public ProductController(IServiceLocator serviceLocator)
       {
           _serviceLocator= serviceLocator;
       }
  }

当您想要使用某项服务时:

ICategoryService categoryService = _serviceLocator.GetService(typeof(categoryService))

MSDN有一篇文章:The Service Locator Pattern解释了乳清使用这种模式。