Normally in software development life cycle as a software
developers we have to test every
possible methods which we have written.In this point Unit test come out. In Unit
testing we are ensure that our method works in expected way.To ensure that our
method should be independent from others. To ensure this isolation we can use
mock objects.
Think that we have method call "A" inside
"A" method we call another method called "B" and get the
return object from "B" to carry out further operation in our method
"A". But since we are unit testing method "A" we can not
depend on method "B". We want to test behavior of our method working
as expected way.What the mock doing is,It allow us to create a mock object (
fake object) which is similar to the
return object of method "B". So our method "A" will
accept this fake object as return object of method "B" and it will
carry out further operation in method "A". Here remember that we have
to use dependency injection design pattern heavily to success this.
Here to implement mock objects I use open source library called Moq. You can download it from here. Now we will implement the example application using Mock.
Think that in a library system we want to calculate membership cost per year and it will depend on the number of books he borrow per one time.
1. Start Visula Studio and create new Class Library called LibraryOperations.
namespace LibraryOperations { public class Member { public int MemberID { get; set; } public string FirstName { get; set; } public string SecondName { get; set; } public int MaximumBookCanBorrow { get; set; } public int Age { get; set; } } }
3. Now create a interface called IMemberManager which is contain all the method required to handle library member. But here we implement only one method.
namespace LibraryOperations { public interface IMemberManager { Member GetMember(int memberID); } }
4.Implement the class called MemeberManager which is inherite from IMemberManager interface.But here we are not going to implement the method body. And you will see the reason soon.
using System; namespace LibraryOperations { public class MemberManager:IMemberManager { public Member GetMember(int memberID) { throw new NotImplementedException(); } } }
5. Now we create a class called LibraryCore and it has a public method called CalculateMemberShipCost. You can see implementation of this class bellow.
namespace LibraryOperations { public class LibraryCore { private readonly IMemberManager _memberManager; public LibraryCore(IMemberManager memberManager) { this._memberManager = memberManager; } public double CalculateMemberShipCost(int memberID) { double membershipCost = 0; Member member = _memberManager.GetMember(memberID); membershipCost = 10 + member.MaximumBookCanBorrow * 0.5; return membershipCost; } } }
Note that here we used Dependency Injection design pattern.This will allow us to create a loose couple class. So we can inject the any type of object which is implement from IMemberManager interface to class constructor.This is the main thing we use to test our method using Mock.
6. Now add the Unit Test project called LibraryOperationsTest to your solution.
Delete UnitTest1.cs class from your test project.
7. Now go to LibraryCore class and right click on CalculateMemberShipCost method name and select Create Unit Tests.
Now Create Unit Tests window will appear. You can select that you want to test in this class and you can select the Out put Test project that the test class want to add.Also you can add any wanted Assembly that you want to use for unit testing.(Here I will not add the our moq library here.Because i rather like to add it using add reference option.If you like you can add it in here).Now click on OK button and VS will create LibraryCoreTest.cs for you.
8. Now we will add Moq.dll to our TestProject using add reference option. Note that here I'm using 4.0 version since I'm using .Net framework 4.Now we will implement our LibraryCoreTest class as bellow.
using LibraryOperations; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using Moq; namespace LibraryOperationsTest { /// <summary> ///This is a test class for LibraryCoreTest and is intended ///to contain all LibraryCoreTest Unit Tests ///</summary> [TestClass()] public class LibraryCoreTest { private LibraryCore _target; private Mock<IMemberManager> _mock; /// <summary> ///A test for CalculateMemberShipCost ///</summary> [TestMethod()] public void CalculateMemberShipCostTest() { _mock = new Mock<IMemberManager>(); _target = new LibraryCore(_mock.Object); Member member = new Member() { MemberID=1, FirstName="Erandika", SecondName="Sandaruwan", Age=25, MaximumBookCanBorrow=4, }; _mock.Setup(x => x.GetMember(It.IsAny<int>())).Returns(member); int memberID = 1; double expected = 12; double actual; actual = _target.CalculateMemberShipCost(memberID); Assert.AreEqual(expected, actual); } } }
Here first we create a mock object using IMemberManager interface and we pass it to LibraryCore constructor.Since we are using dependency Injection in LibraryCore class we can perform this operation.
Mock<IMemberManager> _mock = new Mock<IMemberManager>(); LibraryCore _target = new LibraryCore(_mock.Object);
Then we Create a Member object and tell the assing that object to _mock object. Here you can pass any integer type parameter to our GetMember method and Mock framwork will return member object that we created in all the time when we are calling to the GetMember method.
Member member = new Member() { MemberID=1, FirstName="Erandika", SecondName="Sandaruwan", Age=25, MaximumBookCanBorrow=4, }; _mock.Setup(x => x.GetMember(It.IsAny<int>())).Returns(member);
So other part of our method we can implement in normal way and if we run the unit test now we will get successfully message like this.
Happy Coding :)
Download Source Code here.
2 comments:
Really good article...
Hello,
The Article on How to Use Mock Library For Your Unit Testing In C# is very informative. It give detail information about it .Thanks for Sharing the information unit testing. Software Testing Services
Post a Comment