Implementing Unit Test using MS Test
Owned by Bantyder Bahru (Unlicensed)
1. Implementing Test at the business
In order to start writing unit test there are a couple of things you have to know ,
First as we have discussed earlier all the layers are separated nicely so you need something which simulates the DI task , on which we can configure all dependency required to run our test. For this purpose I will use Moq(Read more: https://code.google.com/p/moq/)
1. Install Moq in your test project
https://code.google.com/p/moq/downloads/detail?name=Moq.4.0.10827.Final.zip&can=2&q=
Extract and reference in your test project
2.Write your test class as shown below
Testing the Services Expand source
//ProductServiceTests.cs [TestClass] public class ProductServiceTest { [TestMethod] public void Can_Add_Product_Service() { //Arrange List<Product> products = new List<Product>() { new Product(){Description="P1",ProductId=1,ProductName="p1Name"}, new Product(){Description="P2",ProductId=2,ProductName="p2Name"}, new Product(){Description="P3",ProductId=3,ProductName="p3Name"}, new Product(){Description="P4",ProductId=4,ProductName="p4Name"}, new Product(){Description="P5",ProductId=5,ProductName="p5Name"}, new Product(){Description="P6",ProductId=6,ProductName="p6Name"} }; Mock<IGenericRepository<Product>> mock1 = new Mock<IGenericRepository<Product>>(); //Here we are going to mock repository GetAll method mock1.Setup(m => m.GetAll()).Returns(products); //Here we are going to mock repository Add method mock1.Setup(m => m.Add(It.IsAny<Product>())).Returns((Product target) => { var original = products.FirstOrDefault( q => q.ProductId == target.ProductId); if (original != null) { return false; } products.Add(target); return true; }); //Now we have our repository ready for property injection //Here we are going to mock our IUnitOfWork Mock<IUnitOfWork> mock = new Mock<IUnitOfWork>(); //Here we are going to inject our repository to the property //mock.SetupProperty(m => m.ProductRepository).SetReturnsDefault(mock1.Object); mock.Setup(m => m.ProductRepository).Returns(mock1.Object); //Now our UnitOfWork is ready to be injected to the service //Here we inject UnitOfWork to constractor of our service ProductService productService = new ProductService(mock.Object); //Act productService.AddProduct(new Product { ProductId = 7, ProductName = "P7Name", Description = "P7" }); var result = productService.GetAllProduct(); var newProduct = result.FirstOrDefault(t => t.ProductId == 7); //Assert Assert.AreEqual(products.Count, result.Count); Assert.AreEqual("P7Name", newProduct.ProductName); Assert.AreEqual("P7", newProduct.Description); } [TestMethod] public void Can_Get_All_Product_Service() { //Arrange List<Product> products = new List<Product>() { new Product(){Description="P1",ProductId=1,ProductName="p1Name"}, new Product(){Description="P2",ProductId=2,ProductName="p2Name"}, new Product(){Description="P3",ProductId=3,ProductName="p3Name"}, new Product(){Description="P4",ProductId=4,ProductName="p4Name"}, new Product(){Description="P5",ProductId=5,ProductName="p5Name"}, new Product(){Description="P6",ProductId=6,ProductName="p6Name"} }; Mock<IGenericRepository<Product>> mock1 = new Mock<IGenericRepository<Product>>(); //Here we are going to mock repository GetAll method mock1.Setup(m => m.GetAll()).Returns(products); //Now we have our repository ready for property injection //Here we are going to mock our IUnitOfWork Mock<IUnitOfWork> mock = new Mock<IUnitOfWork>(); //Here we are going to inject our repository to the property mock.Setup(m => m.ProductRepository).Returns(mock1.Object); //Now our UnitOfWork is ready to be injected to the service //Here we inject UnitOfWork to constractor of our service ProductService productService = new ProductService(mock.Object); //Act var result = productService.GetAllProduct(); //Assert Assert.AreEqual(products,result); } [TestMethod] public void Can_Update_Product_Service() { //Arrange List<Product> products = new List<Product>() { new Product(){Description="P1",ProductId=1,ProductName="p1Name"}, new Product(){Description="P2",ProductId=2,ProductName="p2Name"}, new Product(){Description="P3",ProductId=3,ProductName="p3Name"}, new Product(){Description="P4",ProductId=4,ProductName="p4Name"}, new Product(){Description="P5",ProductId=5,ProductName="p5Name"}, new Product(){Description="P6",ProductId=6,ProductName="p6Name"} }; Mock<IGenericRepository<Product>> mock1 = new Mock<IGenericRepository<Product>>(); //Here we are going to mock repository Edit method mock1.Setup(m => m.Edit(It.IsAny<Product>())).Returns((Product target) => { var original = products.FirstOrDefault( q => q.ProductId == target.ProductId); if (original == null) { return false; } original.ProductName = target.ProductName; original.Description = target.Description; return true; }); //Now we have our repository ready for property injection //Here we are going to mock our IUnitOfWork Mock<IUnitOfWork> mock = new Mock<IUnitOfWork>(); //Here we are going to inject our repository to the property mock.Setup(m => m.ProductRepository).Returns(mock1.Object); //Now our UnitOfWork is ready to be injected to the service //Here we inject UnitOfWork to constractor of our service ProductService productService = new ProductService(mock.Object); //Act var updatedProduct = new Product() {ProductId = 1, ProductName = "p1NameModified", Description = "p1Modified"}; productService.UpdateProduct(updatedProduct); var actualProduct = products.FirstOrDefault(t => t.ProductId == 1); //Assert Assert.AreEqual(actualProduct.ProductName ,updatedProduct.ProductName); Assert.AreEqual(actualProduct.Description, updatedProduct.Description); } [TestMethod] public void Can_Delete_Product_Service() { //Arrange List<Product> products = new List<Product>() { new Product(){Description="P1",ProductId=1,ProductName="p1Name"}, new Product(){Description="P2",ProductId=2,ProductName="p2Name"}, new Product(){Description="P3",ProductId=3,ProductName="p3Name"}, new Product(){Description="P4",ProductId=4,ProductName="p4Name"}, new Product(){Description="P5",ProductId=5,ProductName="p5Name"}, new Product(){Description="P6",ProductId=6,ProductName="p6Name"}, }; Mock<IGenericRepository<Product>> mock1 = new Mock<IGenericRepository<Product>>(); //Here we are going to mock repository FindById Method mock1.Setup(m => m.FindById(It.IsAny<int>())).Returns((int i) => products.Single(x => x.ProductId == i)); //Here we are going to mock repository Delete method mock1.Setup(m => m.Delete(It.IsAny<Product>())).Returns((Product target) => { var original = products.FirstOrDefault( q => q.ProductId == target.ProductId); if (original == null) { return false; } products.Remove(target); return true; }); //Now we have our repository ready for property injection //Here we are going to mock our IUnitOfWork Mock<IUnitOfWork> mock = new Mock<IUnitOfWork>(); //Here we are going to inject our repository to the property mock.Setup(m => m.ProductRepository).Returns(mock1.Object); //Now our UnitOfWork is ready to be injected to the service //Here we inject UnitOfWork to constractor of our service ProductService productService = new ProductService(mock.Object); //Act productService.DeleteProduct(6); var result = products.FirstOrDefault(t => t.ProductId == 6); //Assert Assert.IsNull(result); Assert.IsTrue(products.Count ==5); } [TestMethod] public void Can_Find_By_Id() { //Arrange List<Product> products = new List<Product>() { new Product(){Description="P1",ProductId=1,ProductName="p1Name"}, new Product(){Description="P2",ProductId=2,ProductName="p2Name"}, new Product(){Description="P3",ProductId=3,ProductName="p3Name"}, new Product(){Description="P4",ProductId=4,ProductName="p4Name"}, new Product(){Description="P5",ProductId=5,ProductName="p5Name"}, new Product(){Description="P6",ProductId=6,ProductName="p6Name"} }; Mock<IGenericRepository<Product>> mock1 = new Mock<IGenericRepository<Product>>(); //Here we are going to mock repository FindById Method mock1.Setup(m => m.FindById(It.IsAny<int>())).Returns((int i) => products.Single(x => x.ProductId == i)); //Now we have our repository ready for property injection //Here we are going to mock our IUnitOfWork Mock<IUnitOfWork> mock = new Mock<IUnitOfWork>(); //Here we are going to inject our repository to the property mock.Setup(m => m.ProductRepository).Returns(mock1.Object); //Now our UnitOfWork is ready to be injected to the service //Here we inject UnitOfWork to constractor of our service ProductService productService = new ProductService(mock.Object); //Act var result = productService.GetProduct(6); var expected = products.Single(t => t.ProductId == 6); //Assert Assert.AreEqual(expected,result); } }
2. Implementing Controller unit test
In implementing test on your controller you can achieve UI Test simply, for this purpose I have created sample tests as shown below.
Controller Unit Tests Expand source
// ProductControllerTest.cs [TestClass] public class ProductControllerTest { [TestMethod] public void Can_Paginate() { //Arrange Mock<IProductService> mock= new Mock<IProductService>(); var products = new List<Product>(); mock.Setup(m => m.GetAllProduct()).Returns((new Product[] { new Product(){ProductId=1,ProductName = "P1"} , new Product(){ProductId=2,ProductName = "P2"} , new Product(){ProductId=3,ProductName = "P3"} , new Product(){ProductId=4,ProductName = "P4"} , new Product(){ProductId=5,ProductName = "P5"} }).ToList()); ProductController controller=new ProductController(mock.Object); controller.PageSize = 3; //Act ProductListViewModel result = (ProductListViewModel)controller.Index(2).Model; //Assert Product[] prodArray = result.Products.ToArray(); Assert.IsTrue(prodArray.Length==2); Assert.AreEqual(prodArray[0].ProductName,"P4"); Assert.AreEqual(prodArray[1].ProductName,"P5"); } [TestMethod] public void Can_Generate_Page_Links() { //Arrange -define an Html helper -we need to do this //in order to apply the extension method HtmlHelper myHelper = null; //Arrange -create PagingInfo data PagingInfo pagingInfo = new PagingInfo() { CurrentPage = 2, TotalItems = 28, ItemsPerPage = 10 }; //Arrange -set up the delegate using a lamda expression Func<int, string> pageUrlDelegate = i => "Page" + i; //Act MvcHtmlString result = myHelper.PageLinks(pagingInfo, pageUrlDelegate); //Assert Assert.AreEqual(result.ToString(),@"<a href=""Page1"">1</a>" +@"<a class=""selected"" href=""Page2"">2</a>"+ @"<a href=""Page3"">3</a>"); } [TestMethod] public void Can_Send_Pagination_View_Model() { Mock<IProductService> mock = new Mock<IProductService>(); mock.Setup(m => m.GetAllProduct()).Returns((new Product[] { new Product(){ProductId=1,ProductName = "P1"} , new Product(){ProductId=2,ProductName = "P2"} , new Product(){ProductId=3,ProductName = "P3"} , new Product(){ProductId=4,ProductName = "P4"} , new Product(){ProductId=5,ProductName = "P5"} }).ToList()); ProductController controller = new ProductController(mock.Object); controller.PageSize = 3; //Act ProductListViewModel result = (ProductListViewModel) controller.Index(2).Model; //Assert PagingInfo pagingInfo = result.PagingInfo; Assert.AreEqual(pagingInfo.CurrentPage,2); Assert.AreEqual(pagingInfo.ItemsPerPage,3); Assert.AreEqual(pagingInfo.TotalItems,5); Assert.AreEqual(pagingInfo.TotalPages,2); } }