Monday, July 14, 2014

Understand mocking using Moq framework

If you are bit experience in software development mainly Test Driven Development then you might familiar with those concepts. As this article is not dedicated to discuss mocking, we will very quickly cover the concept and then we will see how mocking can help us in application development.
We know that mocking is something which replaces the actual activity. In software development, there might be situation, where one component is dependent on another component and the dependent component is need to develop at first , in this situation we can implement mock object which will mimic the original functionality.
Mainly in case of Test Driven Development, people write test case at first and the code and we know that,in application one component is dependent on many components, this is the perfect scenario where concept of mocking comes into picture.

To implement mocking, there are many frameworks available, Moq is one of them. It’s free and simple to use. In this article we will see how Moq can use to implement mocking. Point to say that, mocking gets dramatically easy once we inject dependency in class, In this example we have implemented constructor injection to inject dependency.

First of all just give reference of Moq from Nuget package manager to your Unit test project, if you are using visual Studio or you an individually download the Moq dll and give reference to your project.


Once you give reference, you will find the dll in reference directory.  Fine, we have done our primary setup. Now, let’s implement the below code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp
{
    public interface IService
    {
        Boolean Call();
    }
    public class Service : IService
    {
        public Boolean Call()
        {
            throw new Exception();
        }
    }

    public class MockTest
    {
        public readonly IService _service = null;
        public MockTest(IService tmpService)
        {
            _service = tmpService;
        }
        public Boolean Execute()
        {
            if (_service.Call())
                return true;
            else
                return false;
        }

    }
}

The class is extremely simple, Just we have implemented Iservice interface in Service class and MockTest class has Execute function which we will mock using Moq framework. Now, we will implement code for unit test.

[TestClass]
    public class MVCUnitTest
    {
        [TestMethod]
        public void Mock_To_Service_function_Returns_True_always()
        {

            var mock = new Mock<IService>();
            mock.Setup(x => x.Call()).Returns(true);

            var MockTestObject = new MockTest(mock.Object);
            Assert.AreEqual(MockTestObject.Execute(), true);

        }
    }

Here is the output of unit test, we are seeing that the test got pass. Because in mock object we have setup Call() function ,in such a way that it will always return true  in time of call. In face the mocked function will not even call in time of execution.


So, we have learned how to set simple return type of a function.  In need we can set out custom data as returned type from mocked function. Have a look one below example.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp
{
    public interface IUsersInfo
    {
        List<UsersInfo> GetUsers();
    }

    public class UsersInfo : IUsersInfo
    {
        public string username{get;set;}
        public string password {get;set;}
        public List<UsersInfo> GetUsers()
        {
            //It should return below data
            //return new List<UserInfo>
            //{
            //    new UserInfo{username="foo",password="foo"},
            //    new UserInfo{username="sourav",password ="kayal"}
            //};

            throw new NotImplementedException();
        }
    }
    public class MockTest
    {
        public readonly IUsersInfo _userinfo = null;
        public MockTest(IUsersInfo TmpUser)
        {
            _userinfo = TmpUser;
        }
        public List<UsersInfo> GetUser()
        {
            return _userinfo.GetUsers();
        }
    }
}

The GetUsers() function should return a list of UserInfo class , but since it still not implemented we will throw exception in this function intentionally and we will mock the output of the function in time of Unit test to make our unit test pass. Here is the code for unit test.

using System;
using ConsoleApp;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using ConsoleApp;
using System.Collections.Generic;

namespace TestMVC
{
    [TestClass]
    public class MVCUnitTest
    {
        List<UsersInfo> UserInfo = null;
      
        [TestInitialize]
        public void InitializeTest()
        {
            //Create mock return object
             UserInfo = new List<ConsoleApp.UsersInfo>
            {
                new UsersInfo{username="foo",password="foo"},
                new UsersInfo{username="sourav",password ="kayal"}
            };
        }

        [TestMethod]
        public void Mock_To_Service_function_Returns_True_always()
        {
            var mock = new Mock<IUsersInfo>();
             //Setup return data of Mock function
            mock.Setup(x => x.GetUsers()).Returns(UserInfo);

            var MockTestObject = new MockTest(mock.Object);
            Assert.AreEqual(MockTestObject.GetUser(), UserInfo);
        }
    }
}

And once we run the test , we will see that the test got pass. 


Now, in our previous example we have mocked single interface but in need you can mock multiple interface and inject the mocked object as parameter of constructor. In this example we will see how we can mock multiple objects.  Here is the class implementation. 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp
{
    public interface IUsersInfo
    {
        List<UsersInfo> GetUsers();
    }
    public interface IUserInfoById
    {
        UsersInfo GetUserById(int Id);
    }

    public class UsersInfo : IUsersInfo , IUserInfoById
    {
        public string username{get;set;}
        public string password {get;set;}
        public List<UsersInfo> GetUsers()
        {
            //It should return below data
            //return new List<UserInfo>
            //{
            //    new UserInfo{username="foo",password="foo"},
            //    new UserInfo{username="sourav",password ="kayal"}
            //};
            throw new NotImplementedException();
        }
        public UsersInfo GetUserById(int Id)
        {
            throw new NotImplementedException();
        }
    }
    public class MockTest
    {
        public readonly IUsersInfo _userinfo = null;
        public readonly IUserInfoById _userinfoById = null;

        public MockTest(IUsersInfo TmpUser, IUserInfoById TmpUserById)
        {
            _userinfo = TmpUser;
            _userinfoById = TmpUserById;
        }
        public List<UsersInfo> GetUser()
        {
            return _userinfo.GetUsers();
        }
        public UsersInfo GetUserById(int Id)
        {
            return _userinfoById.GetUserById(Id);
        }
    }
}

We are seeing that there are two interfaces which two different classes has implemented, and through constructor of MockTest class we will inject dependency by mocked objects. Here is the code for Unit test.

using System;
using ConsoleApp;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using ConsoleApp;
using System.Collections.Generic;

namespace TestMVC
{
    [TestClass]
    public class MVCUnitTest
    {
        List<UsersInfo> UserInfoList = null;
        UsersInfo UserInfo = null;

        [TestInitialize]
        public void InitializeTest()
        {
            //Create mock return object
            UserInfoList = new List<ConsoleApp.UsersInfo>
            {
                new UsersInfo{username="foo",password="foo"},
                new UsersInfo{username="sourav",password ="kayal"}
            };

            UserInfo = new ConsoleApp.UsersInfo {
                username = "sourav",
                password = "kayal"
            };
        }

        [TestMethod]
        public void Mock_To_Service_function_Returns_True_always()
        {
            var mockUser = new Mock<IUsersInfo>();
            var mockUserbyId = new Mock<IUserInfoById>();

             //Setup return data of Mock function
            mockUser.Setup(x => x.GetUsers()).Returns(UserInfoList);
            mockUserbyId.Setup(x => x.GetUserById(1)).Returns(UserInfo);

            var MockTestObject = new MockTest(mockUser.Object,mockUserbyId.Object);
            Assert.AreEqual(MockTestObject.GetUser(), UserInfoList);
            Assert.AreEqual(MockTestObject.GetUserById(1), UserInfo);
        }
    }
}

And we are seeing that the test got pass because we have created two mock objects one is mockUser and mockUserById, then we save configured two functions by calling Setup() method of mock object. 


Border line:-

Hope you have understood the concept of mocking using Moq framework, In another article I am interested to show various functionality of Moq framework. It’s not that Moq is the best one , few other frameworks like Type Mock etc, gives more functionality then Moq and other free framework. But I think for small and mid size of project with less complexity, those free framework work fine. 


No comments:

Post a Comment