If you have been reading about Unit Testing than you might have heard some of the words like Mocking, Fakes and Stubs. You might wonder what do all these terms mean, what is the difference between a mock and a fake object or why do we need to use mocking when we are doing unit testing? Today I will try to clarify some of these concepts and try to eliminate the confusion that arises in peoples mind when they start with TDD.
Normally when we write code we create a lot of classes and objects to perform discrete tasks. These classes should ideally be cohesive and should do one thing but do it really well. In order to achieve a set of functionality, these classes need to interact with each other. Their communication is normally done via message and delegating functionality to other classes by calling their methods. One of the goals of unit testing is to test a class in isolation. However in our real production code, we have to communicate with other classes to complete the functionality.
Mocking is just a process used in unit testing to handle external dependency. The purpose of mocking is to focus on the code that we want to test and ignore the external dependencies. We can replace external dependencies by mainly 3 types of objects.
Fakes
Fakes are nothing but dumb classes that implement the same interface as the external dependency. However they do not contain the actual business logic code but rather some intermediate code to return the desired results.
Stubs
Stubs are similar to fakes in the sense that they also allow us to mimic the behavior of an interface. The major difference is that normally they are created using mocking frameworks available which allows us to use them with minimal amount of code.
Mocks
Mocks are quite similar to stubs but they have one difference. In your test if you are making an assertion on your stub then it is called a mock. If you are using stub just as an alternate behavior for the real object then they are simple referred to as stubs.
Example
Consider the following code
public interface IRetrieveTaxDetails { Double GetTaxAmount(Double salary); }
In the above code you can see that we have an interface called IRetrieveTaxDetails which contains a method which returns the tax amount based on the salary. The real implementation of this class is not necessary at this point, but what we need to understand is that this class is being utilized in another class
public class SalaryCalculator { private readonly IRetrieveTaxDetails _RetrieveTaxDetails; public SalaryCalculator(IRetrieveTaxDetails retrieveTaxDetails) { _RetrieveTaxDetails = retrieveTaxDetails; } public Double CalculateNetSalary(Double grossSalary) { var taxTobeDeducted = _RetrieveTaxDetails.GetTaxAmount((grossSalary)); return grossSalary - taxTobeDeducted; } }
In the above code you can see that the SalaryCalculator class has a dependency on the instance of the IRetrieveTaxDetails class to complete its functionality. In the context of unit testing this class, we are not interested in finding out whether the IRetrieveTaxDetails implementation is correct or not. We need to find a way to only test the SalaryCalculator class. Thus we can use a mock to do something like this
[TestMethod] public void NetSalaryAfterTaxDeductionFromThirtyThousandIsTwentySevenThousand() { // Arrange var mock = new Mock<IRetrieveTaxDetails>(); mock.Setup(foo => foo.GetTaxAmount(30000)).Returns(3000); var salaryCalculator = new SalaryCalculator(mock.Object); // Act var netSalary = salaryCalculator.CalculateNetSalary(30000); // Assert Assert.AreEqual(27000, netSalary); }
In the above code, I am simply assuming for this tutorial that tax deducted will be at a flat rate of 10%. Thus in my mock object I have specified that if it’s method is activated with value 30,000 then it should simple return 3000. The thing to note here is that I am passing an instance of this mock object to the SalaryCalculator class in it’s constructor rather than the real implementation. Then finally I am asserting that my SalaryCalculator class returned the correct value
In the above example I have used MOQ framework for mocking and I have not asserted anything on the mock object itself thus we will technically call it a stub, if I had asserted on the mock object itself then we would have called it a mock
In the future posts I will try to cover the strategy for unit testing. The most common problem that beginners face in TDD is what to test? This question although seemingly quite simple can be very confusing for the starters. Till then take care of your self and please do not hesitate to contact me if you have any questions.