Moq - Unit Test In .NET Core App Using Mock Object

Introduction

Unit Test is a block of code that helps us in verifying the expected behavior of the other code in isolation; i.e., there is no dependency between the tests. This is a good way to test the application code before it goes for quality assurance (QA). There are three different test frameworks for Unit Testing supported by ASP.NET Core: MSTest, XUnit, and NUnit. All Unit test frameworks offer a similar end goal and help us to write unit tests that are simpler, easier, and faster.

In my previous articles, I have explained how to write unit tests with different frameworks (i.e. MSTest, XUnit, and NUnit). These articles have a very simple and very straightforward example but in the real world, a class's constructor may have a complex object and be injected as a dependency. In this case, we can create a mock object and use it for the unit test.

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.

The Moq library can be added to test projects either by package manager or the .NET CLI tool.

Using Package Manager

PM> Install-Package Moq

Using .net core CLI

dotnet add package Moq

In the following example, the controller class required constructor dependency to create the instance.

MVCProject/Core/IGetDataRepository.cs

namespace MVCproject.Core
{
    public interface IGetDataRepository
    {
        string GetNameById(int id);
    }
}

MVCProject\Infrastructure\EmployeeRepository.cs

using MVCproject.Core;

namespace MVCproject.Infrastructure
{
    public class EmployeeRepository : IGetDataRepository
    {
        public string GetNameById(int id)
        {
            string name;
            if (id == 1)
            {
                name = "Jignesh";
            }
            else if (id == 2)
            {
                name = "Rakesh";
            }
            else
            {
                name = "Not Found";
            }
            return name;
        }
    }
}

MVCProject\Controllers\HomeController.cs

using Microsoft.AspNetCore.Mvc;
using MVCproject.Core;

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

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

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

        public string GetNameById(int id)
        {
            return _data.GetNameById(id);
        }
    }
}

Here, to create a controller class instance, we require the object of IGetDataRepository. Without a mock object, we need to create an object of IGetDataRepository which is real.

Moq library allows us to manipulate the mock object in many ways, such as setting mock methods to return specific values, setting up required properties, and matching the specific arguments when test method is called mock object.

Moq can create a mock version of IGetDataRepository. To demonstrate the code, I am using the MSTest framework. In this example, I am using the Setup and Returns methods to create a mock object. The Setup method is used to tell the mock object how to behave when it calls for a test method and return methods return a specific value.

MockingUnitTest\MSTestProject\UnitTest1.cs

using Microsoft.VisualStudio.TestTools.UnitTesting;
using MVCProject.Controllers;
using Moq;
using Microsoft.Extensions.Logging;
using MVCproject.Core;
using MVCproject.Controllers;

namespace TestProject
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod2()
        {
            var mock = new Mock<IGetDataRepository>();
            mock.Setup(p => p.GetNameById(1)).Returns("Jignesh");
            HomeController home = new HomeController(mock.Object);
            string result = home.GetNameById(1);
            Assert.AreEqual("Jignesh", result);
        }
    }
}

The Moq library is rge same for all the unit test framework. It means that the above test will work with XUnit and NUnit after some syntax modification.

Summary

The Unit test is code where we test all the code paths of the methods and ensure that the results are as expected. A mock object is an object that can act as a real object but can be controlled in test code. It is very useful in generating the objects that are used in the test method.

You can view or download the source code from here.