Phil Fresle's Developer Blog

Unit Testing an ASP.NET MVC 4 Controller using MS Test, Rhino Mocks, AutoMapper and Dependency Injection

I decided to put together a demo project to showcase unit testing an ASP.NET MVC controller. The MVC controller is part of a much larger n-tier solution that stores data in SQL Server, uses Entity Framework, has a data layer using the Repository and Unit of Work patterns, and a service layer on top, but you will see from the testing that all this complexity is hidden and the front end MVC application could be layered on top of mush as far as the MVC and Test projects are concerned.

The controller is designed to implement the standard CRUD (Create, Read, Update, Delete) functionality exposed by a domain service.

The domain model is a simple one, defined as a POCO, and used to manipulate information about a company's branches, namely the "code" they are known by within the company, and their "name".

namespace DemoProject.Model
{
    public class Branch
    {
        public int Id { get; set; }
        public string Code { get; set; }
        public string Name { get; set; }
    }
}

The domain model would be mapped to a View Model for display in the MVC application. In this case there is a 1:1 mapping. This is not always the case as sometimes you do not wish to expose all the domain properties on a view.

using System.ComponentModel.DataAnnotations;

namespace DemoProject.Web.ViewModels
{
    public class BranchViewModel
    {
        public int Id { get; set; }

        [StringLength(10), Required]
        public string Code { get; set; }

        [StringLength(100), Required]
        public string Name { get; set; }
    }
}

The controller is fairly standard other than having the application's Branch Service and the AutoMapper Mapping Engine injected into it as part of the constructor. I used Ninject to perform the injection but any IoC engine would work as well.

These are the two relevant lines of code used in the RegisterServices method of NinjectWebCommon:

kernel.Bind<IMappingEngine>().ToConstant(Mapper.Engine);
kernel.Bind<IBranchService>().To<BranchService>();

These are the lines of code used to setup the AutoMapper mappings:

// domains models to view models
configuration.CreateMap<Branch, BranchViewModel>();
// view models to domain models
configuration.CreateMap<BranchViewModel, Branch>();

AutoMapper is not an essential tool but it removes some of the monotonous repetitive coding of assigning properties from the domain model to the view model and vice versa.

The BranchService that is called from the controller implements this interface:

using System.Collections.Generic;
using DemoProject.Model;

namespace DemoProject.Services
{
    public interface IBranchService
    {
        IEnumerable<Branch> GetAllBranches();
        Branch GetBranchById(int id);
        void CreateNewBranch(Branch branch);
        void ModifyBranch(Branch branch);
        void DeleteBranch(int id);
    }
}

Here is the controller code:

using System.Web.Mvc;
using AutoMapper;
using DemoProject.Model;
using DemoProject.Services;
using DemoProject.Web.ViewModels;

namespace DemoProject.Web.Controllers
{
    public class BranchController : Controller
    {
        private readonly IBranchService _branchService;
        private readonly IMappingEngine _mappingEngine;

        public BranchController(IBranchService branchService, IMappingEngine mappingEngine)
        {
            _branchService = branchService;
            _mappingEngine = mappingEngine;
        }

        public ActionResult Index()
        {
            var vm = new BranchIndexViewModel();
            vm.BranchList = _branchService.GetAllBranches();

            return View(vm);
        }

        public ActionResult Details(int id = 0)
        {
            var dm = _branchService.GetBranchById(id);

            if (dm == null)
                return HttpNotFound();

            // map domain properties to populate view model
            var vm = _mappingEngine.Map<Branch, BranchViewModel>(dm);

            return View(vm);
        }

        public ActionResult Create()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(BranchViewModel vm)
        {
            if (ModelState.IsValid)
            {
                // map view model properties to populate domain model
                var dm = _mappingEngine.Map<BranchViewModel, Branch>(vm);

                _branchService.CreateNewBranch(dm);

                return RedirectToAction("Index");
            }

            return View(vm);
        }

        public ActionResult Edit(int id = 0)
        {
            var dm = _branchService.GetBranchById(id);

            if (dm == null)
                return HttpNotFound();

            // map domain properties to populate view model
            var vm = _mappingEngine.Map<Branch, BranchViewModel>(dm);

            return View(vm);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(BranchViewModel vm)
        {
            if (ModelState.IsValid)
            {
                // map view model properties to populate domain model
                var dm = _mappingEngine.Map<BranchViewModel, Branch>(vm);

                _branchService.ModifyBranch(dm);

                return RedirectToAction("Index");
            }

            return View(vm);
        }

        public ActionResult Delete(int id = 0)
        {
            var dm = _branchService.GetBranchById(id);

            if (dm == null)
                return HttpNotFound();

            // map domain properties to populate view model
            var vm = _mappingEngine.Map<Branch, BranchViewModel>(dm);

            return View(vm);
        }

        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            _branchService.DeleteBranch(id);

            return RedirectToAction("Index");
        }
    }
}

Finally, here are all the unit tests:

using System.Collections.Generic;
using System.Web.Mvc;
using AutoMapper;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Rhino.Mocks;
using DemoProject.Model;
using DemoProject.Services;
using DemoProject.Web.Controllers;
using DemoProject.Web.ViewModels;

namespace DemoProject.Tests.Web
{
    [TestClass]
    public class BranchControllerTests
    {
        private IBranchService _mockService;
        private IMappingEngine _mockMapper;
        private BranchController _controller;

        [TestInitialize]
        public void TestInitialize()
        {
            _mockService = MockRepository.GenerateMock<IBranchService>();
            _mockMapper = MockRepository.GenerateMock<IMappingEngine>();

            _controller = new BranchController(_mockService, _mockMapper);
        }

        [TestCleanup]
        public void TestCleanup()
        {
            _mockService = null;
            _mockMapper = null;

            _controller.Dispose();
            _controller = null;
        }

        #region Index Action Tests
        [TestMethod]
        public void Index_Action_Calls_BranchService_GetAllBranches()
        {
            //Arrange
            _mockService.Stub(x => x.GetAllBranches()).Return(null);

            //Act
            _controller.Index();

            //Assert
            _mockService.AssertWasCalled(x => x.GetAllBranches());
        }

        [TestMethod]
        public void Index_Action_Returns_ViewResult()
        {
            //Arrange
            _mockService.Stub(x => x.GetAllBranches()).Return(null);

            //Act
            var result = _controller.Index();

            //Assert
            Assert.IsInstanceOfType(result, typeof(ViewResult));
        }

        [TestMethod]
        public void Index_Action_Returns_DefaultView()
        {
            //Arrange
            _mockService.Stub(x => x.GetAllBranches()).Return(null);

            //Act
            var result = _controller.Index() as ViewResult;

            //Assert
            Assert.AreEqual("", result.ViewName);
        }

        [TestMethod]
        public void Index_Action_Returns_View_With_BranchIndexViewModel()
        {
            //Arrange
            _mockService.Stub(x => x.GetAllBranches()).Return(null);

            //Act
            var result = _controller.Index() as ViewResult;

            //Assert
            Assert.IsInstanceOfType(result.Model, typeof(BranchIndexViewModel));
        }

        [TestMethod]
        public void Index_Action_Returns_View_With_ViewModel_Containing_Same_Data()
        {
            //Arrange
            var branches = new List<Branch>();
            branches.Add(new Branch { Id = 1, Code = "a", Name = "aaa" });
            branches.Add(new Branch { Id = 2, Code = "b", Name = "bbb" });

            _mockService.Stub(x => x.GetAllBranches()).Return(branches);

            //Act
            var viewResult = _controller.Index() as ViewResult;
            var viewModel = viewResult.Model as BranchIndexViewModel;

            //Assert
            Assert.AreSame(branches, viewModel.BranchList);
        }
        #endregion

        #region Details Action Tests
        [TestMethod]
        public void Details_Action_Calls_BranchService_GetBranchById()
        {
            //Arrange
            _mockService.Stub(x => 
                x.GetBranchById(Arg<int>.Is.Anything)).Return(null);

            //Act
            _controller.Details(1);

            //Assert
            _mockService.AssertWasCalled(x => x.GetBranchById(Arg<int>.Is.Anything));
        }

        [TestMethod]
        public void Details_Action_Calls_GetBranchById_With_Correct_Parameter()
        {
            //Arrange
            int idTestValue = 6;

            _mockService.Expect(x => 
                x.GetBranchById(Arg<int>.Is.Equal(idTestValue))).Return(null);

            //Act
            _controller.Details(idTestValue);

            //Assert (check if id of 6 passed into Details action 
            //then GetById will be also called with id of 6)
            _mockService.VerifyAllExpectations();
        }

        [TestMethod]
        public void Details_Action_Returns_ViewResult()
        {
            //Arrange
            _mockService.Stub(x => x.GetBranchById(Arg<int>.Is.Anything)).
                Return(new Branch { Id = 5, Code = "aa", Name = "aaa" });

            //Act
            var result = _controller.Details(5);

            //Assert
            Assert.IsInstanceOfType(result, typeof(ViewResult));
        }

        [TestMethod]
        public void Details_Action_Returns_DefaultView()
        {
            //Arrange
            _mockService.Stub(x => x.GetBranchById(Arg<int>.Is.Anything)).
                Return(new Branch { Id = 5, Code = "aa", Name = "aaa" });

            //Act
            var result = _controller.Details(5) as ViewResult;

            //Assert
            Assert.AreEqual("", result.ViewName);
        }

        [TestMethod]
        public void Details_Action_Returns_View_With_BranchViewModel()
        {
            //Arrange
            _mockService.Stub(x => x.GetBranchById(Arg<int>.Is.Anything)).
                Return(new Branch { Id = 5, Code = "aa", Name = "aaa" });

            _mockMapper.Stub(x => 
                x.Map<Branch, BranchViewModel>(Arg<Branch>.Is.Anything)).
                Return(new BranchViewModel { Id = 5, Code = "aa", Name = "aaa" });

            //Act
            var result = _controller.Details(5) as ViewResult;

            //Assert
            Assert.IsInstanceOfType(result.Model, typeof(BranchViewModel));
        }

        [TestMethod]
        public void Details_Action_Returns_404_If_No_Branch_Found()
        {
            //Arrange
            // null is returned from GetById when a Branch is not found
            _mockService.Stub(x => 
                x.GetBranchById(Arg<int>.Is.Anything)).Return(null);

            //Act
            var result = _controller.Details(5);

            //Assert
            Assert.IsInstanceOfType(result, typeof(HttpNotFoundResult));
        }
        #endregion

        #region Create Action Tests
        [TestMethod]
        public void Create_Get_Action_Returns_ViewResult()
        {
            //Arrange
            // no prep beyone TestInitialize needed

            //Act
            var result = _controller.Create();

            //Assert
            Assert.IsInstanceOfType(result, typeof(ViewResult));
        }

        [TestMethod]
        public void Create_Get_Action_Returns_DefaultView()
        {
            //Arrange
            // no prep beyone TestInitialize needed

            //Act
            var result = _controller.Create() as ViewResult;

            //Assert
            Assert.AreEqual("", result.ViewName);
        }

        [TestMethod]
        public void Create_Post_Action_Returns_ViewResult_When_Invalid()
        {
            //Arrange
            _controller.ViewData.ModelState.Clear();
            _controller.ModelState.AddModelError("Code", "model is invalid");
            var vm = new BranchViewModel();

            //Act
            var result = _controller.Create(vm);

            //Assert
            Assert.IsInstanceOfType(result, typeof(ViewResult));
        }

        [TestMethod]
        public void Create_Post_Action_Returns_DefaultView_When_Invalid()
        {
            //Arrange
            _controller.ViewData.ModelState.Clear();
            _controller.ModelState.AddModelError("Code", "model is invalid");
            var vm = new BranchViewModel { Id = 0, Code = "", Name = "test" };

            //Act
            var result = _controller.Create(vm) as ViewResult;

            //Assert
            Assert.AreEqual("", result.ViewName);
        }

        [TestMethod]
        public void Create_Post_Action_Returns_Same_Viewmodel_When_Invalid()
        {
            //Arrange
            _controller.ViewData.ModelState.Clear();
            _controller.ModelState.AddModelError("Code", "model is invalid");
            var vm = new BranchViewModel { Id = 0, Code = "", Name = "test" };

            //Act
            var result = _controller.Create(vm) as ViewResult;

            //Assert
            Assert.AreEqual(result.Model, vm);
        }

        [TestMethod]
        public void Create_Post_Action_Calls_Correct_Methods_When_Valid()
        {
            //Arrange
            _mockMapper.Stub(x => 
                x.Map<BranchViewModel, Branch>(Arg<BranchViewModel>.Is.Anything)).
                Return(new Branch { Id = 5, Code = "aa", Name = "aaa" });

            _mockService.Stub(x => x.CreateNewBranch(Arg<Branch>.Is.Anything));

            _controller.ViewData.ModelState.Clear();
            var vm = new BranchViewModel { Id = 5, Code = "aa", Name = "aaa" };

            //Act
            _controller.Create(vm);

            //Assert
            _mockService.AssertWasCalled(x => 
                x.CreateNewBranch((Arg<Branch>.Is.Anything)));
            _mockMapper.AssertWasCalled(x => 
                x.Map<BranchViewModel, Branch>(Arg<BranchViewModel>.Is.Anything));
        }

        [TestMethod]
        public void Create_Post_Action_Returns_RedirectToAction_When_Valid()
        {
            //Arrange
            _mockMapper.Stub(x => 
                x.Map<BranchViewModel, Branch>(Arg<BranchViewModel>.Is.Anything)).
                Return(new Branch { Id = 5, Code = "aa", Name = "aaa" });

            _mockService.Stub(x => x.CreateNewBranch(Arg<Branch>.Is.Anything));

            _controller.ViewData.ModelState.Clear();
            var vm = new BranchViewModel { Id = 5, Code = "aa", Name = "aaa" };

            //Act
            var result = _controller.Create(vm);

            //Assert
            Assert.IsInstanceOfType(result, typeof(RedirectToRouteResult));
        }

        [TestMethod]
        public void Create_Post_Action_Returns_Index_When_Valid()
        {
            //Arrange
            _mockMapper.Stub(x => 
                x.Map<BranchViewModel, Branch>(Arg<BranchViewModel>.Is.Anything)).
                Return(new Branch { Id = 5, Code = "aa", Name = "aaa" });

            _mockService.Stub(x => x.CreateNewBranch(Arg<Branch>.Is.Anything));

            _controller.ViewData.ModelState.Clear();
            var vm = new BranchViewModel { Id = 5, Code = "aa", Name = "aaa" };

            //Act
            var result = _controller.Create(vm) as RedirectToRouteResult;
            var routeValue = result.RouteValues["action"];

            //Assert
            Assert.AreEqual(routeValue, "Index");
        }
        #endregion

        #region Edit Action Tests
        [TestMethod]
        public void Edit_Get_Action_Calls_BranchService_GetBranchById()
        {
            //Arrange
            _mockService.Stub(x => 
                x.GetBranchById(Arg<int>.Is.Anything)).Return(null);

            //Act
            _controller.Edit(1);

            //Assert
            _mockService.AssertWasCalled(x => 
                x.GetBranchById(Arg<int>.Is.Anything));
        }

        [TestMethod]
        public void Edit_Get_Action_Calls_Mapper_If_Branch_Found()
        {
            //Arrange
            var branchDm = new Branch { Id = 1, Code = "a", Name = "aa" };
            _mockService.Stub(x => 
                x.GetBranchById(Arg<int>.Is.Anything)).Return(branchDm);
            _mockMapper.Stub(x => 
                x.Map<Branch, BranchViewModel>(Arg<Branch>.Is.Anything)).
                Return(null);

            //Act
            _controller.Edit(1);

            //Assert
            _mockMapper.AssertWasCalled(x => 
                x.Map<Branch, BranchViewModel>(Arg<Branch>.Is.Anything));
        }

        [TestMethod]
        public void Edit_Get_Action_Returns_ViewResult_If_Branch_Found()
        {
            //Arrange
            var branchDm = new Branch { Id = 1, Code = "a", Name = "aa" };
            var branchVm = new BranchViewModel { Id = 1, Code = "a", Name = "aa" };
            _mockService.Stub(x => 
                x.GetBranchById(Arg<int>.Is.Anything)).Return(branchDm);
            _mockMapper.Stub(x => 
                x.Map<Branch, BranchViewModel>(Arg<Branch>.Is.Anything)).
                Return(branchVm);

            //Act
            var result = _controller.Edit(1);

            //Assert
            Assert.IsInstanceOfType(result, typeof(ViewResult));
        }

        [TestMethod]
        public void Edit_Get_Action_Returns_DefaultView_If_Branch_Found()
        {
            //Arrange
            var branchDm = new Branch { Id = 1, Code = "a", Name = "aa" };
            var branchVm = new BranchViewModel { Id = 1, Code = "a", Name = "aa" };
            _mockService.Stub(x => 
                x.GetBranchById(Arg<int>.Is.Anything)).Return(branchDm);
            _mockMapper.Stub(x => 
                x.Map<Branch, BranchViewModel>(Arg<Branch>.Is.Anything)).
                Return(branchVm);

            //Act
            var result = _controller.Edit(1) as ViewResult;

            //Assert
            Assert.AreEqual("", result.ViewName);
        }

        [TestMethod]
        public void Edit_Get_Action_Returns_Correct_ViewModel_When_Found()
        {
            //Arrange
            var branchDm = new Branch { Id = 1, Code = "a", Name = "aa" };
            var branchVm = new BranchViewModel { Id = 1, Code = "a", Name = "aa" };
            _mockService.Stub(x => 
                x.GetBranchById(Arg<int>.Is.Anything)).Return(branchDm);
            _mockMapper.Stub(x => 
                x.Map<Branch, BranchViewModel>(Arg<Branch>.Is.Anything)).
                Return(branchVm);

            //Act
            var result = _controller.Edit(1) as ViewResult;

            //Assert
            Assert.AreEqual(result.Model, branchVm);
        }

        [TestMethod]
        public void Edit_Get_Action_Returns_404_If_Branch_Not_Found()
        {
            //Arrange
            _mockService.Stub(x => 
                x.GetBranchById(Arg<int>.Is.Anything)).Return(null);

            //Act
            var result = _controller.Edit(1);

            //Assert
            Assert.IsInstanceOfType(result, typeof(HttpNotFoundResult));
        }

        [TestMethod]
        public void Edit_Post_Action_Returns_ViewResult_If_Model_Not_Valid()
        {
            //Arrange
            _controller.ViewData.ModelState.Clear();
            _controller.ModelState.AddModelError("Code", "model is invalid");
            var vm = new BranchViewModel();

            //Act
            var result = _controller.Edit(vm);

            //Assert
            Assert.IsInstanceOfType(result, typeof(ViewResult));
        }

        [TestMethod]
        public void Edit_Post_Action_Returns_DefaultView_When_Invalid()
        {
            //Arrange
            _controller.ViewData.ModelState.Clear();
            _controller.ModelState.AddModelError("Code", "model is invalid");
            var vm = new BranchViewModel { Id = 0, Code = "", Name = "test" };

            //Act
            var result = _controller.Edit(vm) as ViewResult;

            //Assert
            Assert.AreEqual("", result.ViewName);
        }

        [TestMethod]
        public void Edit_Post_Action_Returns_Same_ViewModel_When_Invalid()
        {
            //Arrange
            _controller.ViewData.ModelState.Clear();
            _controller.ModelState.AddModelError("Code", "model is invalid");
            var vm = new BranchViewModel { Id = 0, Code = "", Name = "test" };

            //Act
            var result = _controller.Edit(vm) as ViewResult;

            //Assert
            Assert.AreEqual(result.Model, vm);
        }

        [TestMethod]
        public void Edit_Post_Action_Calls_Correct_Methods_When_Valid()
        {
            //Arrange
            _mockMapper.Stub(x => 
                x.Map<BranchViewModel, Branch>(Arg<BranchViewModel>.Is.Anything)).
                Return(new Branch { Id = 5, Code = "aa", Name = "aaa" });

            _mockService.Stub(x => x.ModifyBranch(Arg<Branch>.Is.Anything));

            _controller.ViewData.ModelState.Clear();

            var vm = new BranchViewModel { Id = 5, Code = "aa", Name = "aaa" };

            //Act
            _controller.Edit(vm);

            //Assert
            _mockService.AssertWasCalled(x => 
                x.ModifyBranch((Arg<Branch>.Is.Anything)));
            _mockMapper.AssertWasCalled(x => 
                x.Map<BranchViewModel, Branch>(Arg<BranchViewModel>.Is.Anything));
        }

        [TestMethod]
        public void Edit_Post_Action_Returns_RedirectToAction_When_Valid()
        {
            //Arrange
            _mockMapper.Stub(x => 
                x.Map<BranchViewModel, Branch>(Arg<BranchViewModel>.Is.Anything)).
                Return(new Branch { Id = 5, Code = "aa", Name = "aaa" });

            _mockService.Stub(x => x.ModifyBranch(Arg<Branch>.Is.Anything));

            _controller.ViewData.ModelState.Clear();

            var vm = new BranchViewModel { Id = 5, Code = "aa", Name = "aaa" };

            //Act
            var result = _controller.Edit(vm);

            //Assert
            Assert.IsInstanceOfType(result, typeof(RedirectToRouteResult));
        }

        [TestMethod]
        public void Edit_Post_Action_Returns_RedirectToAction_Index_When_Valid()
        {
            //Arrange
            _mockMapper.Stub(x => 
                x.Map<BranchViewModel, Branch>(Arg<BranchViewModel>.Is.Anything)).
                Return(new Branch { Id = 5, Code = "aa", Name = "aaa" });

            _mockService.Stub(x => x.ModifyBranch(Arg<Branch>.Is.Anything));

            _controller.ViewData.ModelState.Clear();

            var vm = new BranchViewModel { Id = 5, Code = "aa", Name = "aaa" };

            //Act
            var result = _controller.Edit(vm) as RedirectToRouteResult;
            var routeValue = result.RouteValues["action"];

            //Assert
            Assert.AreEqual(routeValue, "Index");
        }
        #endregion

        #region Delete Action Tests
        [TestMethod]
        public void Delete_Get_Action_Calls_BranchService_GetBranchById()
        {
            //Arrange
            _mockService.Stub(x => 
                x.GetBranchById(Arg<int>.Is.Anything)).Return(null);

            //Act
            _controller.Delete(1);

            //Assert
            _mockService.AssertWasCalled(x => 
                x.GetBranchById(Arg<int>.Is.Anything));
        }

        [TestMethod]
        public void Delete_Get_Action_Calls_Mapper_If_Branch_Found()
        {
            //Arrange
            var branchDm = new Branch { Id = 1, Code = "a", Name = "aa" };
            _mockService.Stub(x => 
                x.GetBranchById(Arg<int>.Is.Anything)).Return(branchDm);
            _mockMapper.Stub(x => 
                x.Map<Branch, BranchViewModel>(Arg<Branch>.Is.Anything)).
                Return(null);

            //Act
            _controller.Delete(1);

            //Assert
            _mockMapper.AssertWasCalled(x => 
                x.Map<Branch, BranchViewModel>(Arg<Branch>.Is.Anything));
        }

        [TestMethod]
        public void Delete_Get_Action_Returns_ViewResult_If_Branch_Found()
        {
            //Arrange
            var branchDm = new Branch { Id = 1, Code = "a", Name = "aa" };
            var branchVm = new BranchViewModel { Id = 1, Code = "a", Name = "aa" };
            _mockService.Stub(x => 
                x.GetBranchById(Arg<int>.Is.Anything)).
                Return(branchDm);
            _mockMapper.Stub(x => 
                x.Map<Branch, BranchViewModel>(Arg<Branch>.Is.Anything)).
                Return(branchVm);

            //Act
            var result = _controller.Delete(1);

            //Assert
            Assert.IsInstanceOfType(result, typeof(ViewResult));
        }

        [TestMethod]
        public void Delete_Get_Action_Returns_DefaultView_If_Branch_Found()
        {
            //Arrange
            var branchDm = new Branch { Id = 1, Code = "a", Name = "aa" };
            var branchVm = new BranchViewModel { Id = 1, Code = "a", Name = "aa" };
            _mockService.Stub(x => 
                x.GetBranchById(Arg<int>.Is.Anything)).
                Return(branchDm);
            _mockMapper.Stub(x => 
                x.Map<Branch, BranchViewModel>(Arg<Branch>.Is.Anything)).
                Return(branchVm);

            //Act
            var result = _controller.Delete(1) as ViewResult;

            //Assert
            Assert.AreEqual("", result.ViewName);
        }

        [TestMethod]
        public void Delete_Get_Action_Returns_Correct_ViewModel_If_Found()
        {
            //Arrange
            var branchDm = new Branch { Id = 1, Code = "a", Name = "aa" };
            var branchVm = new BranchViewModel { Id = 1, Code = "a", Name = "aa" };
            _mockService.Stub(x => 
                x.GetBranchById(Arg<int>.Is.Anything)).Return(branchDm);
            _mockMapper.Stub(x => 
                x.Map<Branch, BranchViewModel>(Arg<Branch>.Is.Anything)).
                Return(branchVm);

            //Act
            var result = _controller.Delete(1) as ViewResult;

            //Assert
            Assert.AreEqual(result.Model, branchVm);
        }

        [TestMethod]
        public void Delete_Get_Action_Returns_404_If_Branch_Not_Found()
        {
            //Arrange
            _mockService.Stub(x => 
                x.GetBranchById(Arg<int>.Is.Anything)).Return(null);

            //Act
            var result = _controller.Delete(1);

            //Assert
            Assert.IsInstanceOfType(result, typeof(HttpNotFoundResult));
        }

        [TestMethod]
        public void Delete_Post_Action_Calls_BranchService_DeleteBranch()
        {
            //Arrange
            _mockService.Stub(x => 
                x.DeleteBranch(Arg<int>.Is.Anything));

            //Act
            _controller.DeleteConfirmed(1);

            //Assert
            _mockService.AssertWasCalled(x => 
                x.DeleteBranch(Arg<int>.Is.Anything));
        }

        [TestMethod]
        public void Delete_Post_Action_Returns_RedirectToAction()
        {
            //Arrange
            _mockService.Stub(x => 
                x.DeleteBranch(Arg<int>.Is.Anything));

            //Act
            var result = _controller.DeleteConfirmed(1);

            //Assert
            Assert.IsInstanceOfType(result, typeof(RedirectToRouteResult));
        }

        [TestMethod]
        public void Delete_Post_Action_Returns_RedirectToAction_Index()
        {
            //Arrange
            _mockService.Stub(x => 
                x.DeleteBranch(Arg<int>.Is.Anything));

            //Act
            var result = _controller.DeleteConfirmed(1) as RedirectToRouteResult;
            var routeValue = result.RouteValues["action"];

            //Assert
            Assert.AreEqual(routeValue, "Index");
        }
        #endregion
    }
}


Feedback

# re: Unit Testing an ASP.NET MVC 4 Controller using MS Test, Rhino Mocks, AutoMapper and Dependency Injection

Good post, but if you are coding in TDD is better to put the unit test first in your post, but it´s a good post. 8/6/2013 11:30 PM | Luis Carlos

# re: Unit Testing an ASP.NET MVC 4 Controller using MS Test, Rhino Mocks, AutoMapper and Dependency Injection

Thank You very much this is very useful post :)
12/18/2013 9:29 AM | Eranga Ranasinghe

# Nice post

It's an amazing post and helps me a lot but I think your method "Edit_Post_Action_Returns_Same_ViewModel_When_Invalid" is wrong because you're passing view model by reference type, so if you change that inside controller's action it'll be always equals because you're changing by reference. 4/30/2014 3:34 PM | Ricardo França