I have a controller in which there are multiple dependencies.And i have made a parameter constructor for that controller,which is taking the object of one of the main dependency(service layer).

 public class ProductController 
 {

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

But in controller there are some methods which are working with multiple dependencies.

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

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

   }

In the above method there is a different dependency CategoryService.And i want to ask to mock that dependency should i need to make different constructor or can i pass multiple dependency object to same constructor ?

有帮助吗?

解决方案

Just inject all dependencies to class you are testing (SUT). You can use constructor or property injection. I would go with constructor injection:

 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();
           // ...
       }
  }

In your tests you can use setup method (NUnit syntax) to create and pass mocked dependencies to 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);
  }

Then you can arrange any of this mocked object in test methods, just before exercising SUT:

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

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

其他提示

Use the service locate pattern: the controller use a service locator to get service instances.

in the constructor:

public class ProductController 
 {
       private IServiceLocator _serviceLocator;


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

when you want to use a certain service:

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

MSDN has an article: The Service Locator Pattern which explain whey use this pattern.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top