8

What is the best way to mock below code in unit testing:

public ActionResult Products()
{
      ViewBag.Title = "Company Product";                        
      IEnumerable<ProductDetailDto> productList =   ProductService.GetAllEffectiveProductDetails();
      ProductModels.ProductCategoryListModel model = new ProductModels.ProductCategoryListModel 
      {     
            //the type of ProductDetails => IEnumerable<productDetailDto>  
            ProductDetails = ProductService.GetAllEffectiveProductDetails(),

            //the type of ProductCategoryList => IEnumerable<selectlistitem>
            ProductCategoryList = productList.Select(x => new SelectListItem
            {
                Value = x.FKProductId.ToString(),
                Text = x.Name
            })
      };
      return View(model);
}

FYI, I am working on VS 2012, MVC 4.0, Unit Testing with MOQ object and TFS setup.

Can anyone help me out on this what is the best test method with mock object for above method?

4
  • I guess you probably want to create a Moq System.Web.HttpContextBase (setting up Moq User, Request, Response, Session, Cache, Server etc as required). Commented Nov 12, 2013 at 11:02
  • yes i want to create MOQ object. Commented Nov 12, 2013 at 11:04
  • Need bit more information. Are your trying to write a Unit test for the above method? And you trying to mock dependencies such as ProductService? You mentioned "What is the best way to mock below code in unit testing". What below code you exactly want to mock here? Commented Nov 12, 2013 at 11:15
  • >>Yes i am trying to write unit test with moq. >>And i want to know how i can mock dependencies like ProductService in my example ? Commented Nov 12, 2013 at 11:23

1 Answer 1

11

If you want to mock ProductService first you need to inject this dependency.

Constructor injection is the most common approach for controllers in ASP.NET MVC.

public class YourController : Controller
{
    private readonly IProductService ProductService;

    /// <summary>
    /// Constructor injection
    /// </summary>
    public YourController(IProductService productService)
    {
        ProductService = productService;
    }

    /// <summary>
    /// Code of this method has not been changed at all.
    /// </summary>
    public ActionResult Products()
    {
        ViewBag.Title = "Company Product";
        IEnumerable<ProductDetailDto> productList = ProductService.GetAllEffectiveProductDetails();
        ProductModels.ProductCategoryListModel model = new ProductModels.ProductCategoryListModel
        {
            //the type of ProductDetails => IEnumerable<productDetailDto>  
            ProductDetails = ProductService.GetAllEffectiveProductDetails(),

            //the type of ProductCategoryList => IEnumerable<selectlistitem>
            ProductCategoryList = productList.Select(x => new SelectListItem
            {
                Value = x.FKProductId.ToString(),
                Text = x.Name
            })
        };
        return View(model);
    }
}

#region DataModels

public class ProductDetailDto
{
    public int FKProductId { get; set; }
    public string Name { get; set; }
}

public class ProductModels
{
    public class ProductCategoryListModel
    {
        public IEnumerable<ProductDetailDto> ProductDetails { get; set; }
        public IEnumerable<SelectListItem> ProductCategoryList { get; set; }
    }
}

#endregion

#region Services

public interface IProductService
    {
        IEnumerable<ProductDetailDto> GetAllEffectiveProductDetails()
    }

public class ProductService : IProductService
{
    public IEnumerable<ProductDetailDto> GetAllEffectiveProductDetails()
    {
        throw new NotImplementedException();
    }
}

#endregion

Then you easily create a mock instance of IProductService, pass it into constructor of YourController, setup GetAllEffectiveProductDetails method and check returned ActionResult and its model.

[TestClass]
public class YourControllerTest
{
    private Mock<IProductService> productServiceMock;

    private YourController target;

    [TestInitialize]
    public void Init()
    {
        productServiceMock = new Mock<IProductService>();

        target = new YourController(
            productServiceMock.Object);
    }

    [TestMethod]
    public void Products()
    {
        //arrange
        // There is a setup of 'GetAllEffectiveProductDetails'
        // When 'GetAllEffectiveProductDetails' method is invoked 'expectedallProducts' collection is exposed.
        var expectedallProducts = new List<ProductDetailDto> { new ProductDetailDto() };
        productServiceMock
            .Setup(it => it.GetAllEffectiveProductDetails())
            .Returns(expectedallProducts);

        //act
        var result = target.Products();

        //assert
        var model = (result as ViewResult).Model as ProductModels.ProductCategoryListModel;
        Assert.AreEqual(model.ProductDetails, expectedallProducts);
        /* Any other assertions */
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

That's exactly the way I would do it too. +1
But in production, will the MVC framework automatically call the controller's constructor with an instance of the IProduceService?
In order to make MVC call controller's constructor with an instance of the IProductService automatically it is needed to implement custom Controller Factory, otherwise you'll get "No parameterless constructor defined for this object" exception. The link below contains an example of the implementation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.