What is Unit Testing?
It is all about testing of every smallest testable block of a code in an automated manner.
Overview of the Repository Pattern
The Repository pattern is intended to create an abstraction layer between the data access layer and the business logic layer of an application. It is a data access pattern that prompts a more loosely coupled approach to data access. We create the data access logic in a separate class, or set of classes, called a repository, with the responsibility of persisting the application's business model.
As the Repository Pattern is useful for decoupling entity operations from presentation, it allows easy mocking and unit testing.
Getting Started
Create a new Project. Open Visual Studio 2012.
File - new - Project
Select Visual C#, then Web in installed templates.
Select ASP.NET MVC 4 Web Application.
Enter the Name and choose the location.
(here, I am giving the name as mvcunittest)
Click OK.
Click OK button.
In the next wizard there is a check box for creating a unit test project. For creating a unit test project select (check) that check box. We can add it later also or also add a new item feature.
Now, we can see the SolutionExplorer as given below:
Now adding a new ADO.NET Entity Data Model and providing it a relevant name.
Click Next and Click New Connection.
Here, I am selecting Microsoft SQL Server option.
Click Continue,
Click Test Connection
From the tables list I am selecting emp table as given below:
Click Finish
Now add a new class in Models:
Right click on Models folder - Add - class
Give the name as EmpRepository.cs
Now my code in EmpRepository.cs:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
-
- namespace mvcunittest.Models
- {
- public class EmpRepository : IEmployeeRepository
- {
- private vrEntities _db = new vrEntities();
- public IEnumerable<emp> GetAllEmployee()
- {
- return _db.emps.ToList();
- }
-
- public void CreateNewEmployee(emp employeeToCreate)
- {
- _db.emps.Add(employeeToCreate);
- _db.SaveChanges();
-
- }
-
- public void DeleteEmployee(int id)
- {
- var conToDel = GetEmployeeByID(id);
- _db.emps.Remove(conToDel);
- _db.SaveChanges();
-
- }
-
- public emp GetEmployeeByID(int id)
- {
- return _db.emps.FirstOrDefault(d => d.empno == id);
- }
-
- public int SaveChanges()
- {
- return _db.SaveChanges();
- }
- }
-
- public interface IEmployeeRepository
- {
- IEnumerable<emp> GetAllEmployee();
- void CreateNewEmployee(emp employeeToCreate);
- void DeleteEmployee(int id);
- emp GetEmployeeByID(int id);
- int SaveChanges();
- }
-
- }
Now add a new controller in the Controllers folder.
(give the name as EmployeeController)
Code in EmployeeController.cs Now, build the project:
Now add View by right-clicking on Index action method in the controller and select strongly typed view and select model class which is created by a data model and select List from scaffold template and click Add.
You can add views in the same way for Create, Delete, Details. Edit scaffold templates.
After adding all the appropriate views, now go to Index.cshtml and we can see some code which is commented as given below,
Now, remove the comment make some changes as the following,
Similarly go to Details.cshtml, remove the comments and make the changes as given below,
Now let's run the application to see the result.
We are now OK with the MVC application using a repository and the Entity Framework.
Now it is the time to work on Unit Testing. First of all create a models folder in the test project:
Give the folder name as Models.
Code in InmemoryEmpRepository.cs - using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using mvcunittest.Models;
- namespace mvcunittest.Tests.Models
- {
- class InmemoryEmpRepository : IEmployeeRepository
- {
- private List<emp> _db = new List<emp>();
-
- public Exception ExceptionToThrow { get; set; }
-
- public IEnumerable<emp> GetAllEmployee()
- {
- return _db.ToList();
- }
-
- public emp GetEmployeeByID(int id)
- {
- return _db.FirstOrDefault(d => d.empno == id);
- }
-
- public void CreateNewEmployee(emp employeeToCreate)
- {
- if (ExceptionToThrow != null)
- throw ExceptionToThrow;
-
- _db.Add(employeeToCreate);
- }
-
- public void SaveChanges(emp employeeToUpdate)
- {
-
- foreach (emp employee in _db)
- {
- if (employee.empno == employeeToUpdate.empno)
- {
- _db.Remove(employee);
- _db.Add(employeeToUpdate);
- break;
- }
- }
- }
-
- public void Add(emp employeeToAdd)
- {
- _db.Add(employeeToAdd);
- }
-
-
- public int SaveChanges()
- {
- return 1;
- }
-
- public void DeleteEmployee(int id)
- {
- _db.Remove(GetEmployeeByID(id));
- }
- }
-
- }
Code in EmployeeControllerTest.cs: - using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using mvcunittest.Controllers;
- using mvcunittest.Models;
- using mvcunittest.Tests.Models;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
- using System.Web.Mvc;
- using System.Web.Routing;
- using System.Web;
- using System.Security.Principal;
-
- namespace mvcunittest.Tests.Controllers
- {
- [TestClass]
- public class EmployeeControllerTest
- {
-
-
-
- [TestMethod]
- public void IndexView()
- {
- var empcontroller = GetEmployeeController(new InmemoryEmpRepository());
- ViewResult result = empcontroller.Index();
- Assert.AreEqual("Index", result.ViewName);
- }
-
-
-
-
-
-
-
- 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;
- }
-
-
-
-
- [TestMethod]
- public void GetAllEmployeeFromRepository()
- {
-
- emp employee1 = GetEmployeeName(1, "ravi", 50000, 10);
- emp employee2 = GetEmployeeName(2, "suri", 50000, 10);
- InmemoryEmpRepository emprepository = new InmemoryEmpRepository();
- emprepository.Add(employee1);
- emprepository.Add(employee2);
- var controller = GetEmployeeController(emprepository);
- var result = controller.Index();
- var datamodel = (IEnumerable<emp>)result.ViewData.Model;
- CollectionAssert.Contains(datamodel.ToList(), employee1);
- CollectionAssert.Contains(datamodel.ToList(), employee2);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- emp GetEmployeeName(int id, string lName, int s, int d)
- {
- return new emp
- {
- empno = id,
- ename = lName,
- sal = s,
- deptno = d
-
- };
- }
-
-
-
-
- [TestMethod]
- public void Create_PostEmployeeInRepository()
- {
- InmemoryEmpRepository emprepository = new InmemoryEmpRepository();
- EmployeeController empcontroller = GetEmployeeController(emprepository);
- emp employee = GetEmployeeID();
- empcontroller.Create(employee);
- IEnumerable<emp> employees = emprepository.GetAllEmployee();
- Assert.IsTrue(employees.Contains(employee));
- }
-
-
-
-
-
- emp GetEmployeeID()
- {
- return GetEmployeeName(1, "ravi", 50000, 10);
- }
-
-
-
-
- [TestMethod]
- public void Create_PostRedirectOnSuccess()
- {
- EmployeeController controller = GetEmployeeController(new InmemoryEmpRepository());
- emp model = GetEmployeeID();
- var result = (RedirectToRouteResult)controller.Create(model);
- Assert.AreEqual("Index", result.RouteValues["action"]);
- }
-
-
-
-
- [TestMethod]
- public void ViewIsNotValid()
- {
- EmployeeController empcontroller = GetEmployeeController(new InmemoryEmpRepository());
- empcontroller.ModelState.AddModelError("", "mock error message");
- emp model = GetEmployeeName(1, "", 0, 0);
- var result = (ViewResult)empcontroller.Create(model);
- Assert.AreEqual("Create", result.ViewName);
- }
-
-
-
-
- [TestMethod]
- public void RepositoryThrowsException()
- {
-
- InmemoryEmpRepository emprepository = new InmemoryEmpRepository();
- Exception exception = new Exception();
- emprepository.ExceptionToThrow = exception;
- EmployeeController controller = GetEmployeeController(emprepository);
- emp employee = GetEmployeeID();
- var result = (ViewResult)controller.Create(employee);
- Assert.AreEqual("Create", result.ViewName);
- ModelState modelState = result.ViewData.ModelState[""];
- Assert.IsNotNull(modelState);
- Assert.IsTrue(modelState.Errors.Any());
- Assert.AreEqual(exception, modelState.Errors[0].Exception);
- }
-
- private class MockHttpContext : HttpContextBase
- {
- private readonly IPrincipal _user = new GenericPrincipal(new GenericIdentity("someUser"), null );
-
- public override IPrincipal User
- {
- get
- {
- return _user;
- }
- set
- {
- base.User = value;
- }
- }
- }
- }
- }
Now run the test cases:
After few seconds, we will see the following screen: