Monday, June 19, 2017

C# Unit Testing: How to write unit test in C# with Moq

This blog will demonstrates how to write the unit test for business object and how to use Moq framework to mock the unit code or dependency of business object and how the DI makes testable unit of code.

basically Unit Test is used to test the unit of work i.e. method and a good unit test should not cross class boundaries and it certainly should not cross network boundaries to access external resource such as Database.

Practicing writing of unit test always enforce to better design and quality of code and also it reduce the cost of project. You can read more benefit of unit testing  



We should design service/component so carefully, it should be testable. If your service have any dependency and it should be abstracted and replaced by interface and resolved by DI.

The below picture depict, how Class X depends on Class Z and Class Y to make external Service call and Database call. To write unit test for Class X method, we need to stub or mock the depended class object behavior by using any mock framework.

C# Unit Testing - Dependency Injection


Here is a business Object – TulipBusiness, which has a method to get yearly sales figure

Abstract Type – Interface

  public interface ITulipBusiness
    {
        decimal GetTulipAnnualSales(int year);
    }
  
Concreate Class

public class TulipBusiness : ITulipBusiness
    {
        ITulipRepository _tulipRepository;

        public TulipBusiness(ITulipRepository tulipRepository)
        {
            _tulipRepository = tulipRepository;
        }
        public decimal GetTulipAnnualSales(int year)
        {
           decimal salesAmount = _tulipRepository.GetTulipYearSales(year);
            if(salesAmount == 0)
            {
                throw new Exception("No Sales Found");
            }
            return salesAmount;
        }
    }
  
In above class, we can see business object depends on repository object to make database call and get yearly sales figure.

As per DI rule, the dependency ‘TulipRepository’ should be abstract and replaced by interface ‘ITulipRepository’

Abstract Type – Interface
  
public interface ITulipRepository
    {
        decimal GetTulipYearSales(int year);

        decimal GetTulipMonthlySales(int year);
    }
  
Concreate Class
  
  public class TulipRepository : ITulipRepository
    {
        public decimal GetTulipMonthlySales(int year)
        {
            throw new NotImplementedException();
        }

        public decimal GetTulipYearSales(int year)
        {
            throw new NotImplementedException();
        }
    }



TulipRepository repository class will be responsible to make database call and get yearly sales figure but it is not implemented yet.

But if you see business class, the dependency of TulipBusiness class is already replaced by interface ITulipRepository and now can easily code the business object based on ITulipRepository type and with help of Moq framework, we can easily mock the repository class behavior and write the unit test for business class.

Here are  few basic unit tests of Business class
  
    [TestClass]
    public class TulipBusinessTest
    {
        TulipBusiness business;
        Mock _repository;

        [TestInitialize]
        public void init()
        {
            _repository = new Mock(MockBehavior.Strict);

            // Mocking Repository Class Methods

            _repository.Setup(x => x.GetTulipYearSales(2014)).Returns(1050.0M);
            _repository.Setup(x => x.GetTulipYearSales(2015)).Returns(1250.0M);

            // For 2016 Years, No Sales
            _repository.Setup(x => x.GetTulipYearSales(2016)).Returns(0);

            // Initlize the business object and inject mocked repostory object through constructor
            business = new TulipBusiness(_repository.Object);
        } 
        
        [TestMethod]
        public void GetTulipSales_20014()
        {
            decimal result = business.GetTulipAnnualSales(2014);

            // expected value, as per mock should be 1050.0M
            Assert.AreEqual(result, 1050.0M); 
        }

        [TestMethod]
        public void GetTulipSales_20015()
        {
            decimal result = business.GetTulipAnnualSales(2015);

            // expected value, as per mock should be 1250.0M
            Assert.AreEqual(result, 1250.0M); 
        }

        [TestMethod]      
        public void GetTulipSales_2016()
        {
            // expecting Exception
            Assert.ThrowsException<Exception>(() => business.GetTulipAnnualSales(2016));

        }
    }
  
In above unit test for business class TulipBusiness, Moq framework is allowed us to create the mimic behavior of Repository object.

Example:

_repository = new Mock(MockBehavior.Strict);

_repository.Setup(x => x.GetTulipYearSales(2014)).Returns(1050.0M); 

GetTulipYearSales method of ITulipRepository repository type is mocked and it always return 1050.0 sales figure, when we pass year as 2014 and in this way we can easily write the unit test and run the unit test without making any database call.


Here is unit test result: 

C# Unit Testing


No comments:

SQL Server - Identify unused indexes

 In this blog, we learn about the index usage information (SYS.DM_DB_INDEX_USAGE_STATS) and analyze the index usage data (USER_SEEKS, USER_S...