Here in this article I am going to explain what Unit is
testing in MVC project. When MVC was launched Unit Testing was promoted as one
of the biggest advantage of using MVC while developing business application.
If your business application growing day by
day then it's became a challenge to keep application on track then Unit testing
plays a vital role in the success of your business application.
Now We will learn Unit testing Step By Step. Here I am
going to create a MVC application first with Entity Framework to perform CRUD
operations.
Open Visual Studio 2012 -> New -> Project

Image 1.

Image 2.
Now your solution will look like below.

Image 3.
Now Right Click on Model Folder -> Add-> ADO.NET
Entity Data Model.

Image 4.

Image 5.

Image 6.

Image 7.

Image 8.

Image 9.

Image 10.
Here we will use repository pattern so Right Click on
Model Folder -> Add New Interface

Image 11.
Define below method in IEmployeeRepository.cs

Image 12.
using System;
using
System.Collections.Generic;
using System.Linq;
using System.Text;
using
System.Threading.Tasks;
namespace
UnitTestingAppInMVC.Models
{
public interface IEmployeeRepository : IDisposable
{
IEnumerable<Employee> GetAllEmployee();
Employee GetEmployeeByID(int emp_ID);
void InsertEmployee(Employee emp);
void DeleteEmployee(int emp_ID);
void UpdateEmployee(Employee emp);
int Save();
}
}
Now again right click on Model Folder -> Add New Class

Image 13.
EmployeeRepository.cs
is
using System;
using
System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
namespace
UnitTestingAppInMVC.Models
{
public class EmployeeRepository : IEmployeeRepository, IDisposable
{
EmployeeManagementEntities context = new EmployeeManagementEntities();
public IEnumerable<Employee>
GetAllEmployee()
{
return context.Employee.ToList();
}
public Employee GetEmployeeByID(int id)
{
return context.Employee.Find(id);
}
public void InsertEmployee(Employee emp)
{
context.Employee.Add(emp);
}
public void DeleteEmployee(int emp_ID)
{
Employee emp =
context.Employee.Find(emp_ID);
context.Employee.Remove(emp);
}
public void UpdateEmployee(Employee emp)
{
context.Entry(emp).State = EntityState.Modified;
}
public int Save()
{
return context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
Now Right
Click on Controller -> Add New Controller.

Image 14.
using System;
using
System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using
UnitTestingAppInMVC.Models;
using PagedList;
using System.Data;
namespace
UnitTestingAppInMVC.Controllers
{
public class EmployeeController : Controller
{
IEmployeeRepository employeeRepository;
public EmployeeController() : this(new EmployeeRepository()) { }
public EmployeeController(IEmployeeRepository repository)
{
employeeRepository = repository;
}
public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page)
{
ViewData["ControllerName"] = this.ToString();
ViewBag.CurrentSort = sortOrder;
ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder)
? "Emp_ID"
: "";
if (searchString != null)
{
page = 1;
}
else
{
searchString = currentFilter;
}
ViewBag.CurrentFilter =
searchString;
var employees = from s in
employeeRepository.GetAllEmployee()
select s;
if (!String.IsNullOrEmpty(searchString))
{
employees = employees.Where(s
=> s.Name.ToUpper().Contains(searchString.ToUpper())
||
s.Name.ToUpper().Contains(searchString.ToUpper()));
}
switch (sortOrder)
{
case "Emp ID":
employees =
employees.OrderByDescending(s => s.Emp_ID);
break;
case "Name":
employees =
employees.OrderBy(s => s.Name);
break;
case "State":
employees =
employees.OrderByDescending(s => s.State);
break;
case "Country":
employees =
employees.OrderByDescending(s => s.Country);
break;
default:
employees =
employees.OrderBy(s => s.Emp_ID);
break;
}
int pageSize = 5;
int pageNumber = (page ?? 1);
return View("Index",
employees.ToPagedList(pageNumber, pageSize));
}
//
// GET: /Employee/Details/5
public ViewResult Details(int id)
{
Employee emp =
employeeRepository.GetEmployeeByID(id);
return View(emp);
}
//
// GET: /Employee/Create
public ActionResult Create()
{
return View("Create");
}
//
// POST: /Employee/Create
[HttpPost]
public ActionResult Create(Employee emp)
{
try
{
if
(ModelState.IsValid)
{
employeeRepository.InsertEmployee(emp);
employeeRepository.Save();
return RedirectToAction("Index");
}
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, "Some Error
Occured.");
}
return View("Create", emp);
}
//
// GET: /Employee/Edit/5
public ActionResult Edit(int id)
{
Employee emp =
employeeRepository.GetEmployeeByID(id);
return View(emp);
}
//
// POST: /Employee/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Employee emp)
{
try
{
if
(ModelState.IsValid)
{
employeeRepository.UpdateEmployee(emp);
employeeRepository.Save();
return RedirectToAction("Index");
}
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, "Some error
Occured.");
}
return View(emp);
}
//
// GET: /employee/Delete/5
public ActionResult Delete(bool? saveChangesError =
false, int id = 0)
{
if (saveChangesError.GetValueOrDefault())
{
ViewBag.ErrorMessage = "Some Error
Occured.";
}
Employee emp =
employeeRepository.GetEmployeeByID(id);
return View(emp);
}
//
// POST: /Employee/Delete/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(int id)
{
try
{
Employee emp =
employeeRepository.GetEmployeeByID(id);
employeeRepository.DeleteEmployee(id);
employeeRepository.Save();
}
catch (Exception ex)
{
return RedirectToAction("Delete", new { id = id,
saveChangesError = true });
}
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
employeeRepository.Dispose();
base.Dispose(disposing);
}
}
}
Now Add View For Index,
Detail, Edit and Delete Action method.
Now
Time To Work on Unit Testing Part.
In
UnitTestingAppInMVC.Tests Add a Folder name with Model.
Right Click on Model Folder -> Add New Class InMemoryEmployeeRepository.cs
using System;
using
System.Collections.Generic;
using System.Linq;
using System.Text;
using
System.Threading.Tasks;
using
UnitTestingAppInMVC.Models;
namespace
UnitTestingAppInMVC.Tests.Models
{
class InMemoryEmployeeRepository : IEmployeeRepository
{
private List<Employee> _db = new List<Employee>();
public Exception ExceptionToThrow { get; set; }
public IEnumerable<Employee>
GetAllEmployee()
{
return _db.ToList();
}
public Employee GetEmployeeByID(int id)
{
return _db.FirstOrDefault(d => d.Emp_ID ==
id);
}
public void InsertEmployee(Employee employeeToCreate)
{
_db.Add(employeeToCreate);
}
public void DeleteEmployee(int id)
{
_db.Remove(GetEmployeeByID(id));
}
public void UpdateEmployee(Employee employeeToUpdate)
{
foreach (Employee employee in _db)
{
if (employee.Emp_ID ==
employeeToUpdate.Emp_ID)
{
_db.Remove(employee);
_db.Add(employeeToUpdate);
break;
}
}
}
public int Save()
{
return 1;
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
//Dispose Object
Here
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
Now
Add A New Controller class EmployeeControllerTest.cs
Here define all your action method as Test Method for which you
want to do unit Testing.
using
Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using
System.Collections.Generic;
using System.Linq;
using
System.Security.Principal;
using System.Text;
using
System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using
UnitTestingAppInMVC.Controllers;
using
UnitTestingAppInMVC.Models;
using
UnitTestingAppInMVC.Tests.Models;
namespace
UnitTestingAppInMVC.Tests.Controllers
{
[TestClass]
public class EmployeeControllerTest
{
/// <summary>
/// This method used for index view
/// </summary>
[TestMethod]
public void IndexView()
{
var empcontroller = GetEmployeeController(new InMemoryEmployeeRepository());
ViewResult result =
empcontroller.Index(null, null, null, null);
Assert.AreEqual("Index", result.ViewName);
Assert.IsInstanceOfType(result, typeof(ViewResult));
}
/// <summary>
/// This method used to get employee
controller
/// </summary>
/// <param
name="repository"></param>
/// <returns></returns>
private static EmployeeController
GetEmployeeController(IEmployeeRepository emprepository)
{
EmployeeController
empcontroller = new EmployeeController(emprepository);
empcontroller.ControllerContext = new ControllerContext()
{
Controller = empcontroller,
RequestContext = new RequestContext(new MockHttpContext(), new RouteData())
};
return empcontroller;
}
/// <summary>
///
This method used to get all employe listing
/// </summary>
[TestMethod]
public void GetAllEmployeeFromRepository()
{
Employee employee1 =
GetEmployeeName(1, "Rahul Saxena", "rahulsaxena@live.com", "Software
Developer",
"Noida",
"Uttar Pradesh", "India");
Employee employee2 = GetEmployeeName(2,
"Abhishek Saxena", "abhishek@abhishek.com", "Tester", "Saharanpur", "Uttar
Pradesh",
"India");
InMemoryEmployeeRepository emprepository = new InMemoryEmployeeRepository();
emprepository.InsertEmployee(employee1);
emprepository.InsertEmployee(employee2);
var controller =
GetEmployeeController(emprepository);
var result = controller.Index(null, null, null, null);
var datamodel = (IEnumerable<Employee>)result.ViewData.Model;
CollectionAssert.Contains(datamodel.ToList(),
employee1);
CollectionAssert.Contains(datamodel.ToList(),
employee2);
}
/// <summary>
/// This method used to get emp name
/// </summary>
/// <param
name="Emp_ID"></param>
/// <param
name="Name"></param>
/// <param
name="Email"></param>
/// <param
name="Designation"></param>
/// <param
name="City"></param>
/// <param
name="State"></param>
/// <param name="Country"></param>
/// <returns></returns>
Employee GetEmployeeName(int Emp_ID, string Name, string Email, string Designation, string City, string State, string Country)
{
return new Employee
{
Emp_ID = Emp_ID,
Name = Name,
Email = Email,
Designation = Designation,
City = City,
State = State,
Country = Country
};
}
/// <summary>
/// This test method used to post employee
/// </summary>
[TestMethod]
public void Create_PostEmployeeInRepository()
{
InMemoryEmployeeRepository emprepository = new InMemoryEmployeeRepository();
EmployeeController empcontroller =
GetEmployeeController(emprepository);
Employee employee = GetEmployeeID();
empcontroller.Create(employee);
IEnumerable<Employee> employees =
emprepository.GetAllEmployee();
Assert.IsTrue(employees.Contains(employee));
}
/// <summary>
///
/// </summary>
/// <returns></returns>
Employee GetEmployeeID()
{
return GetEmployeeName(1, "Rahul
Saxena",
"rahulsaxena@live.com", "Software Developer", "Noida", "Uttar
Pradesh",
"India");
}
/// <summary>
///
/// </summary>
[TestMethod]
public void Create_PostRedirectOnSuccess()
{
EmployeeController controller =
GetEmployeeController(new InMemoryEmployeeRepository());
Employee model = GetEmployeeID();
var result = (RedirectToRouteResult)controller.Create(model);
Assert.AreEqual("Index",
result.RouteValues["action"]);
}
/// <summary>
///
/// </summary>
[TestMethod]
public void ViewIsNotValid()
{
EmployeeController empcontroller =
GetEmployeeController(new InMemoryEmployeeRepository());
empcontroller.ModelState.AddModelError("", "mock error
message");
Employee model = GetEmployeeName(1, "", "", "", "", "", "");
var result = (ViewResult)empcontroller.Create(model);
Assert.AreEqual("Create", result.ViewName);
}
}
public class MockHttpContext : HttpContextBase
{
private readonly IPrincipal _user = new GenericPrincipal(new GenericIdentity("someUser"), null /* roles */);
public override IPrincipal User
{
get
{
return _user;
}
set
{
base.User = value;
}
}
}
}
Now Time to run your test
methods.

Image 18.
See your Test Run result here.

Image 19.