Mocking Database Repository using MOQ Framework


Recently while working on my latest project i got a chance to explore more on MOQ framework.So I am writing the short post on my learning. This code will be applicable in all .net technologies.

This is the second part of previous post. If you are new to moq framework, please refer this post

MOQ-unit test demo in Asp.net Core 2.2

In this post, we will go some deeper on moq framework. We will see how to moq the database while writing the unit test case for Save,Fetch and update functionality.

For simplicity purpose i m taking the Emp class

Step 1: Create the Emp Class in models Folder like this

Step 2: Go to Emp Repository and create the interface like this


using MOQ_Object_Demo.Models;
using System;
using System.Collections.Generic;

namespace MOQ_Object_Demo.Repository
{
    public interface IEmpRepository
    {
        IList FetchAll();
        Emp FindByName(string empName);
        Emp FindById(int empId);
        bool SaveEmp(Emp target);

    }
    public class EmpRepository : IEmpRepository
    {
        public IList FetchAll()
        {
            throw new NotImplementedException();
        }

        public Emp FindById(int empId)
        {
            throw new NotImplementedException();
        }

        public Emp FindByName(string empName)
        {
            throw new NotImplementedException();
        }

        public bool SaveEmp(Emp target)
        {
            throw new NotImplementedException();
        }
    }
}

Step 3: Go to the UnitTest Project and add EmpTest class and write the code like this

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using MOQ_Object_Demo.Models;
using MOQ_Object_Demo.Repository;
using System;
using System.Collections.Generic;
using System.Linq;

namespace UnitTestProject1
{
    [TestClass]
    public class EmpTest
    {
        /// <summary>
        /// Constructor
        /// </summary>
        public EmpTest()
        {
            IList emps = new List
            {
                new Emp { EmpId=1,EmpName="Chandradev", EmpAddress="Bangalore", EmailId="Chandradev@gmail.com"},
                new Emp { EmpId=2,EmpName="Anvi", EmpAddress="Pune", EmailId="Anvi@gmail.com"},
                new Emp { EmpId=3,EmpName="Anu", EmpAddress="Mumbai", EmailId="Anu@gmail.com"}
            };


           //Creating the instance of IEmpRepository interface
            Mock<IEmpRepository> mockEmpRepo = new Mock<IEmpRepository>();

            //Return all the Emp
            mockEmpRepo.Setup(m => m.FetchAll()).Returns(emps);

            //return the Emp by EmpId
            mockEmpRepo.Setup(m => m.FindById(It.IsAny())).Returns((int i) => emps.Where(x => x.EmpId == i).Single());

            //return the Emp by EmpName
            mockEmpRepo.Setup(m => m.FindByName(It.IsAny())).Returns((string str) => emps.Where(x => x.EmpName == str).Single());

            //Saving and updating the Emp data
            mockEmpRepo.Setup(m => m.SaveEmp(It.IsAny())).Returns(
            (Emp target) =>
            {
                DateTime now = DateTime.Now;
                if (target.EmpId.Equals(default(int)))
                {
                    target.DateCreated = now;
                    target.DateModified = now;
                    target.EmpId = emps.Count() + 1;
                    emps.Add(target);

                }
                else
                {
                    var original = emps.Where(m => m.EmpId == target.EmpId).Single();
                    if (original == null)
                    {
                        return false;
                    }
                    original.EmpName = target.EmpName;
                    original.EmpAddress = target.EmpAddress;
                    original.EmpId = target.EmpId;
                    original.DateCreated = now;
                    original.DateModified = now;
                }
                return true;
            });

            //Complete the setup of Mock Emp Repository
            this.MockEmpRepo = mockEmpRepo.Object;

        }

        public IEmpRepository MockEmpRepo { get; private set; }

        public TestContext TestContext { get; set; }


        /// <summary>
        /// verifying the Emp by EmpId
        /// </summary>
        [TestMethod]
        public void ReturnEmpByEmpId()
        {
            //fetch the emp by EmpId 
            Emp testEmp = this.MockEmpRepo.FindById(2);
            Assert.IsNotNull(testEmp);
            Assert.IsInstanceOfType(testEmp, typeof(Emp));
            Assert.AreEqual("Pune", testEmp.EmpAddress);
        }

        /// <summary>
        /// verifying the Emp by EmpName
        /// </summary>
        [TestMethod]
        public void ReturnEmpByEmpName()
        {
            //fetch the empby EmpId 
            Emp testEmp = this.MockEmpRepo.FindByName("Chandradev");
            Assert.IsNotNull(testEmp);
            Assert.IsInstanceOfType(testEmp, typeof(Emp));
            Assert.AreEqual("Bangalore", testEmp.EmpAddress);
        }

        /// <summary>
        /// For fetching all the Emps
        /// </summary>
        [TestMethod]
        public void ReturnAllEmps()
        {
            //Fetching all the Emps List
            IList testEmps = this.MockEmpRepo.FetchAll();
            Assert.IsNotNull(testEmps);
            Assert.AreEqual(3, testEmps.Count);

        }

        /// <summary>
        /// For saving the data
        /// </summary>
        [TestMethod]
        public void Insert_Emp_Data()
        {
            Emp objEmp = new Emp { EmpName = "Ram", EmailId = "Ram@gmail.com", EmpAddress = "Kathmandu" };
            int empCount = this.MockEmpRepo.FetchAll().Count;
            Assert.AreEqual(3, empCount);

            //For saving in repo
            this.MockEmpRepo.SaveEmp(objEmp);

            //To verify that count has been increased
            empCount = this.MockEmpRepo.FetchAll().Count;
            Assert.AreEqual(4, empCount);

            //To verify the newly added record
            Emp testEmp = this.MockEmpRepo.FindByName("Ram");
            Assert.IsNotNull(testEmp);
            Assert.IsInstanceOfType(testEmp, typeof(Emp));
            Assert.AreEqual(4, testEmp.EmpId);
        }

        /// <summary>
        /// Updating the Emp Record
        /// </summary>
        [TestMethod]
        public void Update_Emp_Data()
        {
            //Fetch the Emp Record on basis of Id
            Emp testEmp = this.MockEmpRepo.FindById(1);

            //Change one record of Emp
            testEmp.EmpName = "Chandradev1";

            //Save the Emp Record

            this.MockEmpRepo.SaveEmp(testEmp);

            //Verify the change
            Assert.AreEqual("Chandradev1", this.MockEmpRepo.FindById(1).EmpName);

        }

    }
}

Note: In the above code for sake of simplicity i have taken the Emp list, which could be any repository in real application.

Step 4: Run the test case, you will get output like this

MOQ-unit test demo in Asp.net Core 2.2


In my current project we extensively used MOQ object to create the unit test case for API call method. So in this sample demo example i will explain, what is the scenario to use moq object while writing the unit test case.

what is the moq object ?

>>A mock object is an object that can act as a real object but can be controlled in test code. Moq is a library that allows us to create mock objects in test code. It is also available in NuGet. This library also supports .NET Core

When to use moq object ?

>> We are writing the test case for some method which is using some functionality like After saving the data in database “sending sms or email functionality” should work. But sending sms or email method is the part of some other API service. If we are writing the test case for complete method and service is down for sending sms or email then every time our test case will fail. If that service is taking more time due to some network issue then test case might also fail.

In this scenario to avoid the chance of getting failure of test case, we will use moq object and set to return true. So that our test case will execute smoothly without any problem

The Moq library can be added to test projects using package manager like this

PM> Install-Package Moq

Step 1: create the asp.net core 2.2 application using visual studio 2019/2017 like this

Step 2: Create the repository Folder in solution explorer and add the EmployeeRepository.cs file

Step 3: Add the interface IGetDataRepository in that file as given below


namespace MOQ_Object_Demo.Repository
{
    public interface IGetDataRepository
    {
        string GetEmpAddressByEmpId(int empId);
    }
    public class EmployeeRepository : IGetDataRepository
    {
        public string GetEmpAddressByEmpId(int empId)
        {
            string empAddress = string.Empty;
            if (empId == 1)
            {
                empAddress = "Bangalore";
            }
            else if (empId == 2)
            {
                empAddress = "Pune";
            }
            else
            {
                empAddress = "Not Found";
            }
            return empAddress;
        }
    }
}

Step 4: Go to home controller of application and create the constructor to inject the interface as given below

using Microsoft.AspNetCore.Mvc;
using MOQ_Object_Demo.Models;
using MOQ_Object_Demo.Repository;
using System.Diagnostics;

namespace MOQ_Object_Demo.Controllers
{
    public class HomeController : Controller
    {
       private readonly IGetDataRepository _data;

        public HomeController(IGetDataRepository data)
        {
            _data = data;
        }

        public IActionResult Index()
        {
            ViewBag.address = GetAddressByEmpId(1);
            return View();
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }

        public string GetAddressByEmpId(int empId)
        {
            return _data.GetEmpAddressByEmpId(empId);
        }
    }
}

Step 5: Go to index view and write the code to display address as given below

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>

    <br />
    <p>I am from  @ViewBag.address</p>

</div>

Now our demo project is ready to display employee address, We have to write the test case for GetEmpAddressByEmpId(int empId) method. For this we have to create the Test Project.

Step 6: Create the Test project and add the Moq framework using Nuget package manager

Step 7: Write the test case using moq object as given below

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using MOQ_Object_Demo.Controllers;
using MOQ_Object_Demo.Repository;

namespace UnitTestProject1
{
    [TestClass]
    public class EmpAddressTest
    {
        [TestMethod]
        public void Verify_EmployeeAddress_ByEmpId()
        {
            var mock = new Mock<IGetDataRepository>();

            mock.Setup(p => p.GetEmpAddressByEmpId(1)).Returns("Birganj");

            HomeController home = new HomeController(mock.Object);
            string result = home.GetAddressByEmpId(1);
            Assert.AreEqual("Birganj", result);
        }
    }
}

Explanation:
In the above test method we are creating the mock object of interface using moq framework and setting the value for method return whatever we want.

In the similar way we can set the value for any API and Service method. I have created very simple example to understand the concept of creating moq object and set the value for it.