ASP.NET MVC Model Testing using NUnit and MOQ

Posted by: Mahesh Sabnis , on 3/18/2015, in Category ASP.NET MVC
Views: 63016
Abstract: NUnit and Moq are the suitable frameworks for testing the MVC Model layer separately. This article shows how do use these testing frameworks.

In case of multi-layered applications, each layer must be tested separately for their functionality, so that the consuming layer gets the correct result. There are various approaches to verify the correctness of each layer in the application. Generally, a manual testing approach is followed for testing an application. But in case of manual testing, a lot of efforts goes in while creating testing scripts and soon the time taken for creating testing scripts becomes a major cost factor. Because of the time and cost involved in manual testing, automated testing is recommended. The advantages of automated testing is that the test code is always available with the application code and can be executed at any time to verify the code changes.

 

ASP.NET MVC is now being used prominently for developing multi-layer web applications. MVC itself indicates that we have Model layer for Business operations, Controller layer for handling actions and View layer for UI with DataBinding. The architecture of MVC by default encourages multiple teams to simultaneously work on multiple layers. This makes it possible to test each layer separately. Visual Studio already provides support for testing frameworks where we can perform Unit Testing of our source code. The Developer himself can do this very easily.

Also check: Testing an ASP.NET MVC Controller using NUnit

The following figure shows the mechanism of Testing Framework Availability:

testing-framework

As seen in the image, the Source code can be tested using Testing Frameworks. The Testing framework applies Testing Attributes and uses Asserts to define the Test environment and test result respectively. The Test Runner provides testing statistics to inform the status of the test, whether it succeeded or failed. We can make use of various testing frameworks like Nunit, xUnit.Net, etc. for performing Unit tests. In the article we will be making use of NUnit.

NUnit

NUnit is a Unit Testing framework for all .NET languages and brings in a xUnit style of testing. It provides several attributes which can be used during tests. In our application, we will be making use of the following attributes:

TestFixtureAttribute – is applied on the class that contains test methods. This helps the Test Runner to run tests from this class.

Test – this attribute is applied on a public method containing Test. The method is present inside the class applied with TestFixtureAttribute. This informs the Test Runner to run this method as test.

Nunit also provides Asserts as follows:

  • The Booleans check using Is.True | Is.False.
  • The Equality check using Is.EqualTo | Is.Not.Equal.To
  • The Null check using Is.Null | Is.Not.Null.

More information on NUnit can be obtained over here. Visual Studio provides you with the necessary NUnit references from NuGet Package manager as shown in the following figure:

nunit

Creating an ASP.NET MVC Application

Step 1: Open Visual Studio and create an MVC application of the name ‘MVC5_Testing_1’. In SQL Server, create a database called ‘Company’. In this database, add the following tables.

CREATE TABLE [dbo].[Department] (
    [DeptNo]   INT          NOT NULL,
    [Dname]    VARCHAR (50) NOT NULL,
    [Location] VARCHAR (50) NOT NULL,
    PRIMARY KEY CLUSTERED ([DeptNo] ASC)
);

CREATE TABLE [dbo].[Employee] (
    [EmpNo]   INT          NOT NULL,
    [EmpName] VARCHAR (50) NOT NULL,
    [Salary]  INT          NOT NULL,
    [DeptNo]  INT          NOT NULL,
    PRIMARY KEY CLUSTERED ([EmpNo] ASC),
    FOREIGN KEY ([DeptNo]) REFERENCES [dbo].[Department] ([DeptNo])
);

CREATE TABLE [dbo].[EmployeeInfo] (
    [EmpNo]       INT          IDENTITY (1, 1) NOT NULL,
    [EmpName]     VARCHAR (50) NOT NULL,
    [Salary]      DECIMAL (18) NOT NULL,
    [DeptName]    VARCHAR (50) NOT NULL,
    [Designation] VARCHAR (50) NOT NULL,
    PRIMARY KEY CLUSTERED ([EmpNo] ASC)
);


Step 2: We will add EntityFramework in our application for Data Access. To do so, in the Models folder add a new ADO.NET Entity Data Model and name it as CompanyEDMX. In the wizard, select ‘Generate’ from the Database, select Company database and finally select all tables. After completing the wizard, the table mapping will be generated as shown here.

ef-mapping

Step 3: Since we need to avoid direct calls from the MVC Controller to the EntityFramework, we will add a new folder in the project with the class containing the logic for accessing EntityFramework. Add a folder called ‘ModelAccess’ in the project and add a class file in it with the following logic.

using System.Collections.Generic;
using System.Linq;

using MVC5_Testing_1.Models;

namespace MVC5_Testing_1.ModelAccess
{
    /// <summary>
    /// Interface for providing functionality for Department Data Access
    /// </summary>
    public interface IDepartmentAccess
    {
       List<Department> GetDepartments();
       Department GetDepartment(int id);
       void CreateDepartment(Department dept);
       bool CheckDeptExist(int id);
    }

    /// <summary>
    /// The Department Data Access
    /// </summary>
    public class DepartmentAccess : IDepartmentAccess
    {
        CompanyEntities ctx;
        public DepartmentAccess()
        {
            ctx = new CompanyEntities(); 
        }
        /// <summary>
        /// Get All Departments
        /// </summary>
        /// <returns></returns>
        public List<Department> GetDepartments()
        {
            var depts = ctx.Departments.ToList();
            return depts;
        }
        /// <summary>
        /// Get Department base on Id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Department GetDepartment(int id)
        {
            var dept = ctx.Departments.Find(id);
            return dept;
        }
        /// <summary>
        /// Create Department
        /// </summary>
        /// <param name="dept"></param>
        public void CreateDepartment(Department dept)
        {
            ctx.Departments.Add(dept);
            ctx.SaveChanges();
        }
        /// <summary>
        /// Check whether Department Exist or Not
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool CheckDeptExist(int id)
        {
            var dept = ctx.Departments.Find(id);
            if (dept != null)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}

The above class file contains DepartmentAccess class implementing iDepartmentAccess interface. The class contains the following methods:

  • GetDepartments() - Retrieves all departments from database using EF.
  • GetDepartment() - Retrieves department based on the id.
  • CreateDepartment() - Creates a new Department in the Department table.
  • CheckDepartmentExist() - Check if the department exists in the table.

The above class represents Model layer for our application.

Creating a Test Project

Now it’s time for us to create a test project. We will be using NUnit for this. Since NUnit is a testing framework for all .NET languages, it provides classes for implementing tests.

Step 1: In the solution, add a new class library of the name MVCModelTest. In this project, add references to the NUnit Framework as shown in the following figure:

nunit-packages

We also need to add the NUnit Test Adapter in the project for integrated test execution in Visual Studio. To add this, go to Tools > Extension and Updates, select online and search for NUnit Test Adapter and download as shown in the following figure:

nunuttestadapter

I needed to restart Visual Studio (not sure why).

Step 2: In the class library project, rename Class1.cs to CheckDepartmentTest. In this class add the TestFixture attribute. In this project, add a reference to the MVC project. The following is the complete code:

using MVC5_Testing_1.ModelAccess;
using NUnit.Framework;

namespace MVCModelTest
{
    [TestFixture]
    public class CheckDepartmentTest
    {
        [Test]
        public void CheckDepartmentExist()
        {
            var obj = new DepartmentAccess();

            var Res = obj.CheckDeptExist(10);

            Assert.That(Res, Is.True);
        }
    }
}

The above code makes a call to CheckDeptExist() method of the model class. This method is passed with the value as 10. This is the DeptNo which is available in the Department Table. Currently this test is written for the boolean result Assert. In the class library project, add an App.Config file with the connection string to the Company Database as shown here:

<connectionStrings>
    <add name
="CompanyEntities" connectionString="metadata=res://*/Models.CompanyEDMX.csdl|res://*/Models.CompanyEDMX.ssdl|res://*/Models.CompanyEDMX.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.;initial catalog=Company;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>

Add the EntityFramework NuGet Package manager.

Step 3: Build the Class Library project. In the Test Menu, select the Test Explorer as shown in following figure.

testexplorer

The Test Explorer will show the Test:

test-explorer-test

Right-click on the Test and select Run Selected Test as shown here:

testmethod

The Test Result will be displayed as shown here:

test-result

If the test fails, the result will be as shown here:

test-failed

Implementing Unit Testing using Mocking Framework

In case of enterprise applications, we have components which depend on external dependencies e.g. WCF Services, Databases etc. In such cases, the unit test needs to make calls to the WCF services or to a database. In unit testing, our main objective is to test the functionality of the component and it is difficult to reproduce WCF Service Proxy or the database calls.

In such cases, Mock frameworks can be used to declare a fake object. Using this fake object, we can isolate the code which is making an external call. The fake object now represents a ‘kind of external dependency’. To implement it, we can make use of MOQ. MOQ can be downloaded using a NuGet Package. The following figure shows the arrangement of using Mocking framework for unit testing.

mocking

In our application, the DepartmentDataAccess class contains methods which makes call to the EntityFramework and hence to the database. This is an ideal scenario to make use of Mock framework. In the code, the DepartmentDataAccess class implements the IDepartmentDataAccess interface. We can make use of this interface to build a fake object using Mock<T> generic class.

Step 1: In the MVCModelTest class library project, add MOQ using NuGet package as shown in the following figure:

 

moq

[Test]
public void CheckDepartmentExistWithMoq()
{
    //Create Fake Object
    var fakeObject = new Mock<IDepartmentAccess>();
    //Set the Mock Configuration
    //The CheckDeptExist() method is call is set with the Integer parameter type
    //The Configuration also defines the Return type from the method  
    fakeObject.Setup(x => x.CheckDeptExist(It.IsAny<int>())).Returns(true);
    //Call the methid
    var Res = fakeObject.Object.CheckDeptExist(10);

    Assert.That(Res,Is.True);
}

The above code creates a fake object using Mock (). The generic object accepts an interface which is implemented by the DepartmentAccess class to be tested. The Setup() method of the fake object is used to configure the infrastructure to access the method of the fake object, with the parameter defined using It.IsAny<int>. This parameter specifies the parameter type to the method. The Returns(), method defines the value to be returned by the method. The fake object further makes a call to the CheckDeptExist() method and passes an integer parameter to it. If the method returns true the test will be passed.

Run the test and the result will be displayed as shown here:

result

The advantages of using Moq is, we can unit test the code successfully without using an external dependency object in the test code.

Conclusion: NUnit and Moq are the suitable frameworks for testing the MVC Model layer. The advantage of using MVC is we can test the Model layer separately.

Download the entire source code of this article (Github)

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Mahesh Sabnis is a DotNetCurry author and a Microsoft MVP having over two decades of experience in IT education and development. He is a Microsoft Certified Trainer (MCT) since 2005 and has conducted various Corporate Training programs for .NET Technologies (all versions), and Front-end technologies like Angular and React. Follow him on twitter @maheshdotnet or connect with him on LinkedIn


Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by Nate Doyle on Monday, March 23, 2015 8:46 AM
Interesting, so can controllers be tested separately too? There must be some dependency right?